summaryrefslogtreecommitdiff
path: root/src/engine
diff options
context:
space:
mode:
authorMegaMech <MegaMech@users.noreply.github.com>2024-11-14 23:32:55 -0700
committerGitHub <noreply@github.com>2024-11-14 23:32:55 -0700
commit475f167bb2803999c5116bc285601d1f9a05d7de (patch)
tree859fec292c5c9807cc9690ebf4f0600f558b6063 /src/engine
parent4fbb031dd95f2a84e73fbca269f517e98808d293 (diff)
[modding] Big Update PR (#118)
* Implement kart vehicle * Fix menu CC * Actors * variable framerate * Implement Actors vector * Fix water & scrolling textures * Finish ACoin * Refactor finishline * Refactor mtx to vector * Fix refactored screen code bugs * Fix playlist bug * Switching courses working now * Fix podium ceremony * Mostly Fix Demo and Credits * Credits Load Actors and Textures * Fix credits * Formatting * Update lus and torch * Fix water features * Fix crabs * Combine function * Fix wheels * Add Moon Jump Cheat * Wheel Change * Fix smoke due to wheel change * Fix screens for wheels * Fix transparency * Fix staff ghost * Fix lakitu transition widescreen * Rename and export credits text * Fixes --------- Co-authored-by: MegaMech <7255464+MegaMech@users.noreply.github.com>
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/Actor.cpp8
-rw-r--r--src/engine/Actor.h11
-rw-r--r--src/engine/Matrix.cpp123
-rw-r--r--src/engine/Matrix.h27
-rw-r--r--src/engine/World.cpp57
-rw-r--r--src/engine/World.h28
-rw-r--r--src/engine/actors/ABanana.cpp2
-rw-r--r--src/engine/actors/ABanana.h2
-rw-r--r--src/engine/actors/ACloud.cpp136
-rw-r--r--src/engine/actors/ACloud.h39
-rw-r--r--src/engine/actors/AFinishline.cpp80
-rw-r--r--src/engine/actors/AFinishline.h40
-rw-r--r--src/engine/actors/ATree.cpp66
-rw-r--r--src/engine/actors/ATree.h35
-rw-r--r--src/engine/actors/AWarioSign.cpp1
-rw-r--r--src/engine/courses/BansheeBoardwalk.cpp77
-rw-r--r--src/engine/courses/BansheeBoardwalk.h10
-rw-r--r--src/engine/courses/BigDonut.cpp53
-rw-r--r--src/engine/courses/BigDonut.h6
-rw-r--r--src/engine/courses/BlockFort.cpp39
-rw-r--r--src/engine/courses/BlockFort.h6
-rw-r--r--src/engine/courses/BombKart.cpp28
-rw-r--r--src/engine/courses/BombKart.h38
-rw-r--r--src/engine/courses/BowsersCastle.cpp74
-rw-r--r--src/engine/courses/BowsersCastle.h8
-rw-r--r--src/engine/courses/ChocoMountain.cpp97
-rw-r--r--src/engine/courses/ChocoMountain.h7
-rw-r--r--src/engine/courses/Course.cpp37
-rw-r--r--src/engine/courses/Course.h10
-rw-r--r--src/engine/courses/DKJungle.cpp234
-rw-r--r--src/engine/courses/DKJungle.h8
-rw-r--r--src/engine/courses/DoubleDeck.cpp39
-rw-r--r--src/engine/courses/DoubleDeck.h6
-rw-r--r--src/engine/courses/FrappeSnowland.cpp50
-rw-r--r--src/engine/courses/FrappeSnowland.h8
-rw-r--r--src/engine/courses/KalimariDesert.cpp62
-rw-r--r--src/engine/courses/KalimariDesert.h5
-rw-r--r--src/engine/courses/KoopaTroopaBeach.cpp97
-rw-r--r--src/engine/courses/KoopaTroopaBeach.h9
-rw-r--r--src/engine/courses/LuigiRaceway.cpp51
-rw-r--r--src/engine/courses/LuigiRaceway.h5
-rw-r--r--src/engine/courses/MarioRaceway.cpp68
-rw-r--r--src/engine/courses/MarioRaceway.h6
-rw-r--r--src/engine/courses/MooMooFarm.cpp59
-rw-r--r--src/engine/courses/MooMooFarm.h7
-rw-r--r--src/engine/courses/PodiumCeremony.cpp66
-rw-r--r--src/engine/courses/PodiumCeremony.h6
-rw-r--r--src/engine/courses/RainbowRoad.cpp88
-rw-r--r--src/engine/courses/RainbowRoad.h8
-rw-r--r--src/engine/courses/RoyalRaceway.cpp56
-rw-r--r--src/engine/courses/RoyalRaceway.h6
-rw-r--r--src/engine/courses/SherbetLand.cpp80
-rw-r--r--src/engine/courses/SherbetLand.h8
-rw-r--r--src/engine/courses/Skyscraper.cpp47
-rw-r--r--src/engine/courses/Skyscraper.h6
-rw-r--r--src/engine/courses/TestCourse.cpp113
-rw-r--r--src/engine/courses/TestCourse.h4
-rw-r--r--src/engine/courses/ToadsTurnpike.cpp60
-rw-r--r--src/engine/courses/ToadsTurnpike.h5
-rw-r--r--src/engine/courses/WarioStadium.cpp125
-rw-r--r--src/engine/courses/WarioStadium.h8
-rw-r--r--src/engine/courses/YoshiValley.cpp74
-rw-r--r--src/engine/courses/YoshiValley.h9
-rw-r--r--src/engine/readme.txt3
-rw-r--r--src/engine/vehicles/Boat.cpp2
-rw-r--r--src/engine/vehicles/Bus.cpp2
-rw-r--r--src/engine/vehicles/Car.cpp2
-rw-r--r--src/engine/vehicles/OBombKart.cpp449
-rw-r--r--src/engine/vehicles/OBombKart.h64
-rw-r--r--src/engine/vehicles/TankerTruck.cpp2
-rw-r--r--src/engine/vehicles/Train.cpp2
-rw-r--r--src/engine/vehicles/Truck.cpp2
-rw-r--r--src/engine/wasm.cpp494
73 files changed, 2636 insertions, 1014 deletions
diff --git a/src/engine/Actor.cpp b/src/engine/Actor.cpp
index 1749d4600..b6b2520d0 100644
--- a/src/engine/Actor.cpp
+++ b/src/engine/Actor.cpp
@@ -9,5 +9,9 @@ AActor::AActor() {}
// Virtual functions to be overridden by derived classes
void AActor::Tick() { }
void AActor::Draw(Camera *camera) { }
-void AActor::Collision() {}
-void AActor::Destroy() { } \ No newline at end of file
+void AActor::Collision(Player* player, AActor* actor) {}
+void AActor::Destroy() {
+ // Set uuid to zero.
+ memset(uuid, 0, sizeof(uuid));
+}
+bool AActor::IsMod() { return false; } \ No newline at end of file
diff --git a/src/engine/Actor.h b/src/engine/Actor.h
index 53b5cfa4d..88f5b34a0 100644
--- a/src/engine/Actor.h
+++ b/src/engine/Actor.h
@@ -7,13 +7,12 @@ extern "C" {
#include "main.h"
#include "camera.h"
#include "common_structs.h"
-}
+
class AActor {
public:
- uint8_t uuid[16];
- /* 0x00 */ s16 Type;
+ /* 0x00 */ s16 Type = 0;
/* 0x02 */ s16 Flags;
/* 0x04 */ s16 Unk_04;
/* 0x06 */ s16 State;
@@ -24,6 +23,7 @@ public:
/* 0x18 */ Vec3f Pos;
/* 0x24 */ Vec3f Velocity = {0, 0, 0};
/* 0x30 */ Collision Unk30;
+ uint8_t uuid[16];
virtual ~AActor() = default; // Virtual destructor for proper cleanup in derived classes
@@ -31,6 +31,9 @@ public:
virtual void Tick();
virtual void Draw(Camera*);
- virtual void Collision();
+ virtual void Collision(Player* player, AActor* actor);
virtual void Destroy();
+ virtual bool IsMod();
};
+
+} \ No newline at end of file
diff --git a/src/engine/Matrix.cpp b/src/engine/Matrix.cpp
new file mode 100644
index 000000000..7b8c3b1fb
--- /dev/null
+++ b/src/engine/Matrix.cpp
@@ -0,0 +1,123 @@
+#include <libultraship.h>
+#include <libultra/gbi.h>
+#include "engine/World.h"
+
+extern "C" {
+#include "common_structs.h"
+}
+
+void AddMatrix(std::vector<Mtx>& stack, Mat4 mtx, s32 flags) {
+ // Reserve space if needed to avoid reallocation overhead
+ stack.reserve(1000);
+
+ // Push a new matrix to the stack
+ stack.emplace_back();
+
+ // Convert to a fixed-point matrix
+ guMtxF2L(mtx, &stack.back());
+
+ // Load the matrix
+ gSPMatrix(gDisplayListHead++, &stack.back(), flags);
+}
+
+Mtx* GetMatrix(std::vector<Mtx>& stack) {
+ stack.emplace_back();
+ return &stack.back();
+}
+
+/**
+ * Use GetMatrix first
+ */
+void AddMatrixFixed(std::vector<Mtx>& stack, s32 flags) {
+ // Load the matrix
+ gSPMatrix(gDisplayListHead++, &stack.back(), flags);
+}
+
+// Used in func_80095BD0
+void SetTextMatrix(f32 arg1, f32 arg2, f32 arg3, f32 arg4) {
+ Mat4 mtx;
+ mtx[0][0] = arg3;
+ mtx[0][1] = 0.0f;
+ mtx[0][2] = 0.0f;
+ mtx[0][3] = 0.0f;
+ mtx[1][0] = 0.0f;
+ mtx[1][1] = arg4;
+ mtx[1][2] = 0.0f;
+ mtx[1][3] = 0.0f;
+ mtx[2][0] = 0.0f;
+ mtx[2][1] = 0.0f;
+ mtx[2][2] = 1.0f;
+ mtx[2][3] = 0.0f;
+ mtx[3][0] = arg1;
+ mtx[3][1] = arg2;
+ mtx[3][2] = 0.0f;
+ mtx[3][3] = 1.0f;
+
+ AddMatrix(gWorldInstance.Mtx.Effects, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+}
+
+
+// API
+extern "C" {
+
+ void AddHudMatrix(Mat4 mtx, s32 flags) {
+ AddMatrix(gWorldInstance.Mtx.Hud, mtx, flags);
+ }
+
+ void AddObjectMatrix(Mat4 mtx, s32 flags) {
+ AddMatrix(gWorldInstance.Mtx.Objects, mtx, flags);
+ }
+
+ void AddShadowMatrix(Mat4 mtx, s32 flags) {
+ AddMatrix(gWorldInstance.Mtx.Shadows, mtx, flags);
+ }
+
+ void AddKartMatrix(Mat4 mtx, s32 flags) {
+ AddMatrix(gWorldInstance.Mtx.Karts, mtx, flags);
+ }
+
+ void AddEffectMatrix(Mat4 mtx, s32 flags) {
+ AddMatrix(gWorldInstance.Mtx.Effects, mtx, flags);
+ }
+
+ void AddEffectMatrixFixed(s32 flags) {
+ AddMatrixFixed(gWorldInstance.Mtx.Effects, flags);
+ }
+
+ void AddEffectMatrixOrtho(void) {
+ auto& stack = gWorldInstance.Mtx.Effects;
+ stack.emplace_back();
+
+ guOrtho(&stack.back(), 0.0f, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, 0.0f, -100.0f, 100.0f, 1.0f);
+
+ gSPMatrix(gDisplayListHead++, &stack.back(), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
+ }
+
+ Mtx* GetEffectMatrix(void) {
+ return GetMatrix(gWorldInstance.Mtx.Effects);
+ }
+
+
+ /**
+ * Note that the game doesn't seem to clear all of these at the beginning of a new frame.
+ * We might need to adjust which ones we clear.
+ */
+ void ClearMatrixPools(void) {
+ gWorldInstance.Mtx.Hud.clear();
+ gWorldInstance.Mtx.Objects.clear();
+ gWorldInstance.Mtx.Shadows.clear();
+ gWorldInstance.Mtx.Karts.clear();
+ gWorldInstance.Mtx.Effects.clear();
+ }
+
+ void ClearHudMatrixPool(void) {
+ gWorldInstance.Mtx.Hud.clear();
+ }
+ void ClearEffectsMatrixPool(void) {
+ gWorldInstance.Mtx.Effects.clear();
+ }
+
+ void ClearObjectsMatrixPool(void) {
+ gWorldInstance.Mtx.Objects.clear();
+ }
+}
diff --git a/src/engine/Matrix.h b/src/engine/Matrix.h
new file mode 100644
index 000000000..b0be2bf87
--- /dev/null
+++ b/src/engine/Matrix.h
@@ -0,0 +1,27 @@
+#ifndef _MATRIX_HEADER_
+#define _MATRIX_HEADER_
+
+#include <libultraship.h>
+
+#include "common_structs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void ClearMatrixPools(void);
+void AddHudMatrix(Mat4 mtx, s32 flags);
+void AddObjectMatrix(Mat4 mtx, s32 flags);
+void AddEffectMatrix(Mat4 mtx, s32 flags);
+void AddEffectMatrixOrtho(void);
+void AddEffectMatrixFixed(s32 flags);
+void SetTextMatrix(f32 arg1, f32 arg2, f32 arg3, f32 arg4);
+Mtx* GetEffectMatrix(void);
+void ClearHudMatrixPool(void);
+void ClearEffectsMatrixPool(void);
+void ClearObjectsMatrixPool(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _MATRIX_HEADER_ \ No newline at end of file
diff --git a/src/engine/World.cpp b/src/engine/World.cpp
index 01c6f13bd..a5bbd6cdf 100644
--- a/src/engine/World.cpp
+++ b/src/engine/World.cpp
@@ -9,6 +9,7 @@
#include "vehicles/Bus.h"
#include "vehicles/TankerTruck.h"
#include "vehicles/Car.h"
+#include "vehicles/OBombKart.h"
#include "TrainCrossing.h"
#include <memory>
@@ -75,7 +76,7 @@ void World::AddCar(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoin
cars++;
}
-void World::ResetVehicles(void) {
+void World::ClearVehicles(void) {
trains = trucks = busses = tankerTrucks = cars = boats = 0;
Vehicles.clear();
}
@@ -86,6 +87,10 @@ TrainCrossing* World::AddCrossing(Vec3f position, u32 waypointMin, u32 waypointM
return crossing.get();
}
+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));
+}
+
u32 World::GetCupIndex() {
return this->CupIndex;
}
@@ -164,28 +169,52 @@ Object* World::AddObject(std::unique_ptr<GameObject> object) {
return &rawPtr->o;
}
-AActor* World::AddActor(std::unique_ptr<AActor> actor) {
- AActor* rawPtr = actor.get();
- Actors.push_back(std::move(actor));
- return rawPtr;
+AActor* World::AddActor(AActor* actor) {
+ Actors.push_back(actor);
+ return Actors.back();
}
-void World::TickActors() {
- for (auto& actor : Actors) {
- actor->Tick();
- }
+struct Actor* World::AddBaseActor() {
+ Actors.push_back(new AActor());
+ // Skip C++ vtable to access variables in C
+ return reinterpret_cast<struct Actor*>(reinterpret_cast<char*>(Actors.back()) + sizeof(void*));
+}
+
+/**
+ * Converts a C struct Actor* to its C++ AActor class
+ */
+AActor* World::ConvertActorToAActor(Actor* actor) {
+ // Move the ptr back so that it points at the vtable.
+ // Which is the initial item in the class, or in other words
+ // Point to the class.
+ return reinterpret_cast<AActor*>((char*)actor - sizeof(void*));
}
-void World::DrawActors(Camera* camera) {
- for (auto& actor : Actors) {
- actor->Draw(camera);
+/**
+ * Converts a C++ AActor class to a C Actor* struct.
+ */
+Actor* World::ConvertAActorToActor(AActor* actor) {
+ // Move the ptr forward past the vtable.
+ // This allows C to access the class variables like a normal Actor* struct.
+ return reinterpret_cast<Actor*>((char*)actor + sizeof(void*));
+}
+
+AActor* World::GetActor(size_t index) {
+ return Actors[index];
+}
+
+void World::TickActors() {
+ for (AActor* actor : Actors) {
+ if (actor->IsMod()) {
+ actor->Tick();
+ }
}
}
void RemoveExpiredActors() {
- //Actors.erase(
+ // Actors.erase(
// std::remove_if(Actors.begin(), Actors.end(),
- // [](const std::unique_ptr<AActor>& actor) { return actor->uuid == 0; }), // Example condition
+ // [](const std::unique_ptr<AActor>& actor) { return actor->uuid == 0; }),
// Actors.end());
}
diff --git a/src/engine/World.h b/src/engine/World.h
index a2947499a..ee562118b 100644
--- a/src/engine/World.h
+++ b/src/engine/World.h
@@ -6,6 +6,7 @@
#include "vehicles/Vehicle.h"
#include "vehicles/Train.h"
#include "vehicles/Car.h"
+#include "vehicles/OBombKart.h"
#include "TrainCrossing.h"
#include <memory>
#include "Actor.h"
@@ -64,15 +65,27 @@ class World {
SkyboxColours Skybox;
} Properties;
+ typedef struct {
+ std::vector<Mtx> Hud;
+ std::vector<Mtx> Objects;
+ std::vector<Mtx> Shadows;
+ std::vector<Mtx> Karts;
+ std::vector<Mtx> Effects;
+ } Matrix;
+
public:
explicit World();
void AddCourse(Course* course);
- AActor* AddActor(std::unique_ptr<AActor> actor);
+ AActor* AddActor(AActor* actor);
+ struct Actor* AddBaseActor();
+ AActor* GetActor(size_t index);
+
void TickActors();
- void DrawActors(Camera* camera);
void RemoveExpiredActors();
+ AActor* ConvertActorToAActor(Actor* actor);
+ Actor* ConvertAActorToActor(AActor* actor);
Object* AddObject(std::unique_ptr<GameObject> object);
@@ -99,6 +112,8 @@ public:
void NextCourse(void);
void PreviousCourse(void);
+ Matrix Mtx;
+
// Holds all available courses
Course* CurrentCourse;
@@ -108,8 +123,9 @@ public:
size_t CupIndex = 1;
std::vector<std::unique_ptr<GameObject>> GameObjects;
- std::vector<std::unique_ptr<AActor>> Actors;
+ std::vector<AActor*> Actors;
+ /** Actors */
void AddBoat(f32 speed, uint32_t waypoint);
void AddTrain(size_t numCarriages, f32 speed, uint32_t waypoint);
void AddTruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint);
@@ -117,7 +133,11 @@ public:
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;
- void ResetVehicles(void);
+ void ClearVehicles(void);
+
+ /** Objects **/
+ void AddBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C);
+ std::vector<std::unique_ptr<OBombKart>> BombKarts;
TrainCrossing* AddCrossing(Vec3f position, u32 waypointMin, u32 waypointMax, f32 approachRadius, f32 exitRadius);
std::vector<std::shared_ptr<TrainCrossing>> Crossings;
diff --git a/src/engine/actors/ABanana.cpp b/src/engine/actors/ABanana.cpp
index c26efca24..d484ab983 100644
--- a/src/engine/actors/ABanana.cpp
+++ b/src/engine/actors/ABanana.cpp
@@ -54,7 +54,7 @@ void ABanana::Tick() {
void ABanana::Draw(Camera *camera) {
render_actor_banana(camera, NULL, (BananaActor*)this);
}
-void ABanana::Collision() { }
+void ABanana::Collision(Player* player, AActor*) { }
void ABanana::Destroy() { }
//void ABanana::Held() {}
diff --git a/src/engine/actors/ABanana.h b/src/engine/actors/ABanana.h
index 5ef8900d6..0da9eb98f 100644
--- a/src/engine/actors/ABanana.h
+++ b/src/engine/actors/ABanana.h
@@ -16,6 +16,6 @@ public:
// Virtual functions to be overridden by derived classes
virtual void Tick() override;
virtual void Draw(Camera*) override;
- virtual void Collision() override;
+ virtual void Collision(Player*, AActor*) override;
virtual void Destroy() override;
};
diff --git a/src/engine/actors/ACloud.cpp b/src/engine/actors/ACloud.cpp
new file mode 100644
index 000000000..d3eaad32d
--- /dev/null
+++ b/src/engine/actors/ACloud.cpp
@@ -0,0 +1,136 @@
+#include <libultraship.h>
+
+#include "ACloud.h"
+#include "engine/Actor.h"
+#include "World.h"
+
+extern "C" {
+#include "macros.h"
+#include "common_structs.h"
+#include "math_util.h"
+#include "actor_types.h"
+#include "actors.h"
+extern f32 gKartHopInitialVelocityTable[];
+extern f32 gKartGravityTable[];
+}
+
+ACloud::ACloud(Vec3f pos) {
+ Pos[0] = pos[0];
+ Pos[1] = pos[1];
+ Pos[2] = pos[2];
+ Rot[0] = 0;
+ Rot[1] = 0;
+ Rot[2] = 0;
+
+ //Flags = -0x8000 | 0x4000;
+
+ BoundingBoxSize = 2.0f;
+}
+
+void ACloud::Tick() {
+ Rot[1] += 0x200;
+
+ if (PickedUp) {
+ Timer++; // Increment timer
+ }
+
+ if (Timer > 500) { // Time has expired, reset the actor and player
+ PickedUp = false;
+ if (_player) {
+ gKartHopInitialVelocityTable[_player->characterId] = OldHop; // reset back to normal
+ gKartGravityTable[_player->characterId] = OldGravity;
+ _player = NULL; // Reset
+ }
+ Timer = 0;
+ }
+}
+
+extern Gfx cloud_mesh[];
+
+void ACloud::Draw(Camera *camera) {
+ Mat4 mtx;
+
+ if (PickedUp) {
+ return; // Skip drawing if the actor has been picked up
+ }
+
+ mtxf_pos_rotation_xyz(mtx, Pos, Rot);
+ if (render_set_position(mtx, 0) != 0) {
+ gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)cloud_mesh);
+ }
+}
+
+void ACloud::Collision(Player* player, AActor* actor) {
+ if (!PickedUp) {
+ if (query_collision_player_vs_actor_item(player, gWorldInstance.ConvertAActorToActor(actor))) {
+ // Player has picked up the actor, activate the cloud effect
+ _player = player;
+ PickedUp = true;
+
+ OldHop = gKartHopInitialVelocityTable[player->characterId];
+ OldGravity = gKartGravityTable[player->characterId];
+ gKartHopInitialVelocityTable[player->characterId] = Hop;
+ gKartGravityTable[player->characterId] = Gravity;
+ }
+ }
+}
+
+bool ACloud::IsMod() { return true; }
+
+Vtx cloud_mesh_vtx_cull[8] = {
+ {{ {0, -4, -4}, 0, {0, 0}, {0, 0, 0, 0} }},
+ {{ {0, -4, 4}, 0, {0, 0}, {0, 0, 0, 0} }},
+ {{ {0, 4, 4}, 0, {0, 0}, {0, 0, 0, 0} }},
+ {{ {0, 4, -4}, 0, {0, 0}, {0, 0, 0, 0} }},
+ {{ {0, -4, -4}, 0, {0, 0}, {0, 0, 0, 0} }},
+ {{ {0, -4, 4}, 0, {0, 0}, {0, 0, 0, 0} }},
+ {{ {0, 4, 4}, 0, {0, 0}, {0, 0, 0, 0} }},
+ {{ {0, 4, -4}, 0, {0, 0}, {0, 0, 0, 0} }},
+};
+
+Vtx cloud_mesh_vtx_0[4] = {
+ {{ {0, 4, 4}, 0, {-524, -530}, {255, 255, 255, 166} }},
+ {{ {0, -4, 4}, 0, {-530, 1516}, {255, 255, 255, 201} }},
+ {{ {0, -4, -4}, 0, {1516, 1522}, {255, 255, 255, 188} }},
+ {{ {0, 4, -4}, 0, {1522, -524}, {255, 255, 255, 154} }},
+};
+
+Gfx cloud_mesh_tri_0[] = {
+ gsSPVertex(cloud_mesh_vtx_0 + 0, 4, 0),
+ gsSP2Triangles(0, 1, 2, 0, 0, 2, 3, 0),
+ gsSPEndDisplayList(),
+};
+
+Gfx mat_cloud_cutout[] = {
+ gsSPSetGeometryMode(G_ZBUFFER | G_SHADE | G_FOG | G_SHADING_SMOOTH),
+ gsSPClearGeometryMode(G_CULL_FRONT | G_CULL_BACK | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | G_CLIPPING),
+ gsDPPipeSync(),
+ gsDPSetCombineLERP(TEXEL0, PRIMITIVE, PRIMITIVE, TEXEL1, 0, 0, 0, TEXEL0, COMBINED, 0, PRIMITIVE, 0, 0, 0, 0, COMBINED),
+ gsSPSetOtherMode(G_SETOTHERMODE_H, 4, 20, G_AD_NOISE | G_CD_MAGICSQ | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_PERSP | G_CYC_2CYCLE | G_PM_NPRIMITIVE),
+ gsSPSetOtherMode(G_SETOTHERMODE_L, 0, 32, G_AC_NONE | G_ZS_PIXEL | G_RM_FOG_SHADE_A | G_RM_AA_ZB_TEX_EDGE2),
+ gsSPTexture(65535, 65535, 0, 0, 1),
+ gsDPSetPrimColor(0, 0, 255, 220, 203, 255),
+ gsDPSetTextureImage(G_IM_FMT_I, G_IM_SIZ_8b_LOAD_BLOCK, 1, gTexture69C4E4),
+ gsDPSetTile(G_IM_FMT_I, G_IM_SIZ_8b_LOAD_BLOCK, 0, 0, 7, 0, G_TX_WRAP | G_TX_NOMIRROR, 0, 0, G_TX_WRAP | G_TX_NOMIRROR, 0, 0),
+ gsDPLoadBlock(7, 0, 0, 511, 512),
+ gsDPSetTile(G_IM_FMT_I, G_IM_SIZ_8b, 4, 0, 0, 0, G_TX_WRAP | G_TX_NOMIRROR, 5, 1, G_TX_WRAP | G_TX_NOMIRROR, 5, 1),
+ gsDPSetTileSize(0, 98, 100, 124, 124),
+ gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b_LOAD_BLOCK, 1, gTexture66C8F4),
+ gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b_LOAD_BLOCK, 0, 128, 6, 0, G_TX_WRAP | G_TX_NOMIRROR, 0, 0, G_TX_WRAP | G_TX_NOMIRROR, 0, 0),
+ gsDPLoadBlock(6, 0, 0, 1023, 256),
+ gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, 128, 1, 0, G_TX_CLAMP | G_TX_NOMIRROR, 5, 0, G_TX_CLAMP | G_TX_NOMIRROR, 5, 0),
+ gsDPSetTileSize(1, 0, 0, 124, 124),
+ gsSPEndDisplayList(),
+};
+
+Gfx cloud_mesh[] = {
+ //gsSPClearGeometryMode(G_LIGHTING),
+ //gsSPVertex(cloud_mesh_vtx_cull + 0, 8, 0),
+ gsSPSetGeometryMode(G_LIGHTING),
+ //gsSPCullDisplayList(0, 7),
+ gsSPDisplayList(mat_cloud_cutout),
+ gsSPDisplayList(cloud_mesh_tri_0),
+ gsSPEndDisplayList(),
+};
+
diff --git a/src/engine/actors/ACloud.h b/src/engine/actors/ACloud.h
new file mode 100644
index 000000000..3d266243c
--- /dev/null
+++ b/src/engine/actors/ACloud.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <libultraship.h>
+#include "engine/Actor.h"
+
+extern "C" {
+#include "macros.h"
+#include "main.h"
+#include "camera.h"
+#include "common_structs.h"
+}
+
+class ACloud : public AActor {
+public:
+
+
+ // Constructor
+ ACloud(Vec3f pos);
+
+ virtual ~ACloud() override = default;
+
+ // Virtual functions to be overridden by derived classes
+ virtual void Tick() override;
+ virtual void Draw(Camera*) override;
+ virtual void Collision(Player* player, AActor* actor) override;
+ virtual bool IsMod() override;
+
+ bool PickedUp = false;
+ uint32_t Timer = 0;
+
+ Player* _player = NULL;
+
+ f32 Hop = 3.0f;
+ f32 Gravity = 200.0f;
+
+ f32 OldHop = 0;
+ f32 OldGravity = 0;
+
+};
diff --git a/src/engine/actors/AFinishline.cpp b/src/engine/actors/AFinishline.cpp
new file mode 100644
index 000000000..cc920f2bb
--- /dev/null
+++ b/src/engine/actors/AFinishline.cpp
@@ -0,0 +1,80 @@
+#include <libultraship.h>
+#include <libultra/gbi.h>
+
+#include "AFinishline.h"
+#include "engine/Actor.h"
+#include "World.h"
+#include "assets/common_data.h"
+
+extern "C" {
+#include "macros.h"
+#include "common_structs.h"
+#include "math_util.h"
+#include "actor_types.h"
+#include "actors.h"
+extern f32 gKartHopInitialVelocityTable[];
+extern f32 gKartGravityTable[];
+}
+
+AFinishline::AFinishline(Vec3f pos) {
+ if (pos != nullptr) { // Allow user to set their own values
+ Pos[0] = pos[0];
+ Pos[1] = pos[1] - 15;
+ Pos[2] = pos[2];
+ } else { // Default to first waypoint position
+ Pos[0] = D_80164490->posX;
+ Pos[1] = (f32) (D_80164490->posY - 15);
+ Pos[2] = D_80164490->posZ;
+ }
+
+ Rot[0] = 0;
+ Rot[1] = 0;
+ Rot[2] = 0;
+
+
+
+ Flags = -0x8000 | 0x4000;
+
+ BoundingBoxSize = 0.0f;
+}
+
+void AFinishline::Tick() {}
+
+extern Gfx cloud_mesh[];
+
+void AFinishline::Draw(Camera *camera) {
+ Mat4 mtx;
+ s16 temp = Pos[2];
+ s32 maxObjectsReached;
+
+
+ if (gGamestate == CREDITS_SEQUENCE) {
+ return;
+ }
+
+ mtxf_pos_rotation_xyz(mtx, Pos, Rot);
+
+ maxObjectsReached = render_set_position(mtx, 0) == 0;
+ if (maxObjectsReached) {
+ return;
+ }
+
+ if (temp < camera->pos[2]) {
+ if (D_800DC5BC != 0) {
+
+ gDPSetFogColor(gDisplayListHead++, D_801625EC, D_801625F4, D_801625F0, 0xFF);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D001C20);
+ } else {
+ gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D001B90);
+ }
+ } else if (D_800DC5BC != 0) {
+ gDPSetFogColor(gDisplayListHead++, D_801625EC, D_801625F4, D_801625F0, 0xFF);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D001C88);
+ } else {
+ gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D001BD8);
+ }
+}
+
+void AFinishline::Collision(Player* player, AActor* actor) {}
+
+bool AFinishline::IsMod() { return true; }
diff --git a/src/engine/actors/AFinishline.h b/src/engine/actors/AFinishline.h
new file mode 100644
index 000000000..ea27f3b61
--- /dev/null
+++ b/src/engine/actors/AFinishline.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <libultraship.h>
+#include "engine/Actor.h"
+
+extern "C" {
+#include "macros.h"
+#include "main.h"
+#include "camera.h"
+#include "common_structs.h"
+}
+
+class AFinishline : public AActor {
+public:
+ /**
+ * Default behaviour places the finishline at the first waypoint.
+ * @arg pos, optional. Sets a custom position
+ */
+ AFinishline(Vec3f pos = nullptr);
+
+ virtual ~AFinishline() override = default;
+
+ // Virtual functions to be overridden by derived classes
+ virtual void Tick() override;
+ virtual void Draw(Camera*) override;
+ virtual void Collision(Player* player, AActor* actor) override;
+ virtual bool IsMod() override;
+
+ bool PickedUp = false;
+ uint32_t Timer = 0;
+
+ Player* _player = NULL;
+
+ f32 Hop = 3.0f;
+ f32 Gravity = 200.0f;
+
+ f32 OldHop = 0;
+ f32 OldGravity = 0;
+
+};
diff --git a/src/engine/actors/ATree.cpp b/src/engine/actors/ATree.cpp
new file mode 100644
index 000000000..fa1c7f580
--- /dev/null
+++ b/src/engine/actors/ATree.cpp
@@ -0,0 +1,66 @@
+#include "ATree.h"
+
+#include <libultra/gbi.h>
+
+extern "C" {
+#include "common_structs.h"
+#include "math_util.h"
+#include "main.h"
+#include "actors.h"
+}
+
+ATree::ATree(Vec3f pos, Gfx* displaylist, f32 drawDistance, f32 minDrawDistance, const char* tlut = nullptr) {
+ Pos[0] = pos[0];
+ Pos[1] = pos[1];
+ Pos[2] = pos[2];
+
+ Displaylist = displaylist;
+ Tlut = tlut;
+ DrawDistance = drawDistance;
+ MinDrawDistance = minDrawDistance;
+}
+
+void ATree::Tick() {
+ if (((Flags & 0x800) == 0) && ((Flags & 0x400) != 0)) {
+ Pos[1] = Pos[1] + 4.0f;
+ if (Pos[1] > 800.0f) {
+ Flags |= 0x800;
+ }
+ }
+}
+
+void ATree::Draw(Camera* camera) {
+ f32 dist;
+
+ if ((Flags & 0x800) != 0) {
+ return;
+ }
+
+ dist = is_within_render_distance(camera->pos, Pos, camera->rot[1], 0, gCameraZoom[camera - camera1],
+ DrawDistance);
+
+ if (CVarGetInteger("gNoCulling", 0) == 1) {
+ dist = MAX(dist, 0.0f);
+ }
+
+ if (dist < 0.0f) {
+ return;
+ }
+
+ if (((Flags & 0x400) == 0) && (dist < MinDrawDistance)) {
+ func_8029794C(Pos, Rot, 3.0f);
+ }
+ sBillBoardMtx[3][0] = Pos[0];
+ sBillBoardMtx[3][1] = Pos[1];
+ sBillBoardMtx[3][2] = Pos[2];
+
+ if (render_set_position(sBillBoardMtx, 0) != 0) {
+ if (Tlut) {
+ gDPLoadTLUT_pal256(gDisplayListHead++, Tlut);
+ }
+ gSPDisplayList(gDisplayListHead++, Displaylist);
+ }
+}
+
+void ATree::Collision(Player* player, AActor*) { }
+void ATree::Destroy() { }
diff --git a/src/engine/actors/ATree.h b/src/engine/actors/ATree.h
new file mode 100644
index 000000000..eb51f6e7e
--- /dev/null
+++ b/src/engine/actors/ATree.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <libultraship.h>
+#include "engine/Actor.h"
+
+extern "C" {
+#include "common_structs.h"
+}
+
+
+// Note that this doesn't seem to work right
+// Use add_actor_to_empty_slot(test, rot, vel, ACTOR_TREE_MARIO_RACEWAY);
+// to spawn stock actors
+class ATree : public AActor {
+public:
+
+ Gfx* Displaylist;
+ const char* Tlut;
+ f32 DrawDistance;
+ f32 MinDrawDistance;
+ s16 Flags = -0x8000 | 0x4000;
+ s16 State = 0x43;
+ f32 BoundingBoxSize = 3.0f;
+ f32 Unk_08 = 20.0f;
+
+ virtual ~ATree() = default;
+
+ // Set tlut to NULL if not using a tlut
+ explicit ATree(Vec3f pos, Gfx* displaylist, f32 drawDistance, f32 minDrawDistance, const char* tlut);
+
+ virtual void Tick() override;
+ virtual void Draw(Camera* camera) override;
+ virtual void Collision(Player*, AActor*) override;
+ virtual void Destroy() override;
+};
diff --git a/src/engine/actors/AWarioSign.cpp b/src/engine/actors/AWarioSign.cpp
index 2dd8a5fc9..8e73a94f3 100644
--- a/src/engine/actors/AWarioSign.cpp
+++ b/src/engine/actors/AWarioSign.cpp
@@ -15,7 +15,6 @@ AWarioSign::AWarioSign(Vec3f pos) {
Pos[2] = pos[2];
}
- // Virtual functions to be overridden by derived classes
void AWarioSign::Tick() {
Rot[1] += 0xB6;
}
diff --git a/src/engine/courses/BansheeBoardwalk.cpp b/src/engine/courses/BansheeBoardwalk.cpp
index 09517031d..2211b3294 100644
--- a/src/engine/courses/BansheeBoardwalk.cpp
+++ b/src/engine/courses/BansheeBoardwalk.cpp
@@ -6,7 +6,8 @@
#include "BansheeBoardwalk.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/actors/AFinishline.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/banshee_boardwalk_data.h"
#include "assets/boo_frames.h"
@@ -102,13 +103,42 @@ BansheeBoardwalk::BansheeBoardwalk() {
Props.Skybox.FloorTopLeft = {0, 0, 0};
}
+void BansheeBoardwalk::Load() {
+ Course::Load();
+
+ D_800DC5BC = 1;
+ D_801625EC = 0;
+ D_801625F4 = 0;
+ D_801625F0 = 0;
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_banshee_boardwalk_track_sections));
+ func_80295C6C();
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000878), 128, 0, 0, 0);
+ D_8015F8E4 = -80.0f;
+}
+
void BansheeBoardwalk::LoadTextures() {
}
void BansheeBoardwalk::SpawnActors() {
+ gWorldInstance.AddActor(new AFinishline());
+
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_banshee_boardwalk_item_box_spawns));
}
+void BansheeBoardwalk::SpawnVehicles() {
+ if (gModeSelection == VERSUS) {
+ Vec3f pos = {0, 0, 0};
+
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][110], 110, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][190], 190, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][250], 250, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][475], 475, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][610], 610, 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 BansheeBoardwalk::MinimapSettings() {
D_80165880 = dma_textures((const char*)gTextureGhosts, 0x4CC2, 0xD980);
@@ -188,27 +218,12 @@ void BansheeBoardwalk::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-void BansheeBoardwalk::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(140, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(165, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(330, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(550, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(595, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void BansheeBoardwalk::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void BansheeBoardwalk::SetStaffGhost() {
-}
-
-void BansheeBoardwalk::BeginPlay() { }
-
void BansheeBoardwalk::Render(struct UnkStruct_800DC5EC* arg0) {
Camera* camera = arg0->camera;
Mat4 spCC;
@@ -274,18 +289,7 @@ void BansheeBoardwalk::RenderCredits() {
void BansheeBoardwalk::Collision() {}
-void BansheeBoardwalk::GenerateCollision() {
- D_800DC5BC = 1;
- D_801625EC = 0;
- D_801625F4 = 0;
- D_801625F0 = 0;
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_banshee_boardwalk_track_sections));
- func_80295C6C();
- find_vtx_and_set_colours(segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07000878)), 128, 0, 0, 0);
- D_8015F8E4 = -80.0f;
-}
-
-void BansheeBoardwalk::Water() {
+void BansheeBoardwalk::ScrollingTextures() {
D_802B87BC++;
if (D_802B87BC >= 0x100) {
@@ -306,4 +310,21 @@ void BansheeBoardwalk::Waypoints(Player* player, int8_t playerId) {
}
}
+void BansheeBoardwalk::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) {
+ gDPPipeSync(gDisplayListHead++);
+ gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
+ gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
+ gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_XLU_INTER, G_RM_NOOP2);
+ gDPSetBlendMask(gDisplayListHead++, 0xFF);
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
+ // d_course_banshee_boardwalk_packed_dl_878
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07000878));
+ gDPSetAlphaCompare(gDisplayListHead++, G_AC_NONE);
+ gDPPipeSync(gDisplayListHead++);
+}
+
+void BansheeBoardwalk::CreditsSpawnActors() {
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000878), 0x32, 0, 0, 0);
+}
+
void BansheeBoardwalk::Destroy() { }
diff --git a/src/engine/courses/BansheeBoardwalk.h b/src/engine/courses/BansheeBoardwalk.h
index c8ef58a6b..612597578 100644
--- a/src/engine/courses/BansheeBoardwalk.h
+++ b/src/engine/courses/BansheeBoardwalk.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
@@ -35,14 +37,12 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
- virtual void Water() override;
+ virtual void ScrollingTextures() override;
virtual void Waypoints(Player*, int8_t) override;
+ virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override;
+ virtual void CreditsSpawnActors() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/BigDonut.cpp b/src/engine/courses/BigDonut.cpp
index 18c8e65a4..f01930c7b 100644
--- a/src/engine/courses/BigDonut.cpp
+++ b/src/engine/courses/BigDonut.cpp
@@ -6,7 +6,7 @@
#include "BigDonut.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/big_donut_data.h"
extern "C" {
@@ -98,11 +98,42 @@ BigDonut::BigDonut() {
Props.Skybox.FloorTopLeft = {0, 0, 0};
}
+void BigDonut::Load() {
+ Course::Load();
+
+ // d_course_big_donut_packed_dl_1018
+ generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07001018), 6);
+ // d_course_big_donut_packed_dl_450
+ generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000450), 6);
+ // d_course_big_donut_packed_dl_AC0
+ generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000AC0), 6);
+ // d_course_big_donut_packed_dl_B58
+ generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000B58), 6);
+ // d_course_big_donut_packed_dl_230
+ generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000230), 6);
+ func_80295C6C();
+ D_8015F8E4 = 100.0f;
+}
+
void BigDonut::LoadTextures() {
}
void BigDonut::SpawnActors() {}
+void BigDonut::SpawnVehicles() {
+ if (gModeSelection == VERSUS) {
+ Vec3f pos = {0, 0, 0};
+
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][20], 20, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][40], 40, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][60], 60, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][80], 80, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][100], 100, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][120], 120, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][140], 140, 0, 1.0f);
+ }
+}
+
// Likely sets minimap boundaries
void BigDonut::MinimapSettings() {
D_8018D2A0 = 0.0257f;
@@ -118,17 +149,12 @@ void BigDonut::WhatDoesThisDo(Player* player, int8_t playerId) {}
void BigDonut::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-void BigDonut::SpawnBombKarts() {}
-
// Positions the finishline on the minimap
void BigDonut::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void BigDonut::SetStaffGhost() {}
-
-void BigDonut::BeginPlay() {}
void BigDonut::Render(struct UnkStruct_800DC5EC* arg0) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -156,21 +182,6 @@ void BigDonut::RenderCredits() {}
void BigDonut::Collision() {}
-void BigDonut::GenerateCollision() {
- // d_course_big_donut_packed_dl_1018
- generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07001018), 6);
- // d_course_big_donut_packed_dl_450
- generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000450), 6);
- // d_course_big_donut_packed_dl_AC0
- generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000AC0), 6);
- // d_course_big_donut_packed_dl_B58
- generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000B58), 6);
- // d_course_big_donut_packed_dl_230
- generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000230), 6);
- func_80295C6C();
- D_8015F8E4 = 100.0f;
-}
-
void BigDonut::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = 0;
}
diff --git a/src/engine/courses/BigDonut.h b/src/engine/courses/BigDonut.h
index 41fd0457f..732a9a568 100644
--- a/src/engine/courses/BigDonut.h
+++ b/src/engine/courses/BigDonut.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
@@ -33,13 +35,9 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/BlockFort.cpp b/src/engine/courses/BlockFort.cpp
index e81550a64..d6ebf2263 100644
--- a/src/engine/courses/BlockFort.cpp
+++ b/src/engine/courses/BlockFort.cpp
@@ -6,7 +6,7 @@
#include "BlockFort.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/block_fort_data.h"
extern "C" {
@@ -101,10 +101,34 @@ BlockFort::BlockFort() {
Props.Skybox.FloorTopLeft = {216, 232, 248};
}
+void BlockFort::Load() {
+ Course::Load();
+
+ generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x070015C0), 1);
+ func_80295C6C();
+ D_8015F8E4 = gCourseMinY - 10.0f;
+}
+
void BlockFort::LoadTextures() {
}
-void BlockFort::SpawnActors() {}
+void BlockFort::SpawnActors() {
+ spawn_all_item_boxes((ActorSpawnData*)LOAD_ASSET_RAW(d_course_block_fort_item_box_spawns));
+}
+
+void BlockFort::SpawnVehicles() {
+ if (gModeSelection == VERSUS) {
+ Vec3f pos = {0, 0, 0};
+
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][20], 20, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][40], 40, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][60], 60, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][80], 80, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][100], 100, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][120], 120, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][140], 140, 0, 1.0f);
+ }
+}
// Likely sets minimap boundaries
void BlockFort::MinimapSettings() {
@@ -121,17 +145,12 @@ void BlockFort::WhatDoesThisDo(Player* player, int8_t playerId) {}
void BlockFort::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-void BlockFort::SpawnBombKarts() {}
-
// Positions the finishline on the minimap
void BlockFort::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void BlockFort::SetStaffGhost() {}
-
-void BlockFort::BeginPlay() { }
void BlockFort::Render(struct UnkStruct_800DC5EC* arg0) {
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
@@ -145,12 +164,6 @@ void BlockFort::RenderCredits() {}
void BlockFort::Collision() {}
-void BlockFort::GenerateCollision() {
- generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x070015C0), 1);
- func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
-}
-
void BlockFort::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = 0;
}
diff --git a/src/engine/courses/BlockFort.h b/src/engine/courses/BlockFort.h
index eba210234..b3d2fdc3c 100644
--- a/src/engine/courses/BlockFort.h
+++ b/src/engine/courses/BlockFort.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
@@ -33,13 +35,9 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
virtual void Waypoints(Player*, int8_t) override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/BombKart.cpp b/src/engine/courses/BombKart.cpp
deleted file mode 100644
index 1cbbd7477..000000000
--- a/src/engine/courses/BombKart.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "BombKart.h"
-
-extern "C" {
- #include "bomb_kart.h"
-}
-
-/**
- * BombKarts derive their Y position from the waypoint Y value or 'spawn_actor_on_surface' function
- */
-
-OBombKart::OBombKart(uint16_t waypoint, uint16_t state, float unk_04, float x, float z, float unk_10, float unk_14) {}
-
-void OBombKart::Init() {
- // BombKarts.emplace_back(this);
- //BombKarts.push_back(BombKarts(waypoint, state, unk_04, x, z, unk_10, unk_14));
-}
-
-void OBombKart::Update() {
-
-}
-
-void OBombKart::Render() {
-
-}
-
-void OBombKart::Explode() {
-
-} \ No newline at end of file
diff --git a/src/engine/courses/BombKart.h b/src/engine/courses/BombKart.h
deleted file mode 100644
index e11bf6820..000000000
--- a/src/engine/courses/BombKart.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef BOMBKART_H
-#define BOMBKART_H
-
-#include <libultraship.h>
-
-
-#ifdef __cplusplus
-#include "GameObject.h"
-extern "C" {
-#endif
-
- #include "bomb_kart.h"
- #include "Engine.h"
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifdef __cplusplus
-
-class OBombKart : public GameObject {
-
-public:
- virtual ~OBombKart() = default;
-
- // Constructor
- explicit OBombKart(uint16_t waypoint, uint16_t state, float unk_04, float x, float z, float unk_10, float unk_14);
-
- BombKart vehicle;
- virtual void Init();
- virtual void Update();
- virtual void Render();
- virtual void Explode();
-};
-
-#endif
-
-#endif // BOMBKART_H \ No newline at end of file
diff --git a/src/engine/courses/BowsersCastle.cpp b/src/engine/courses/BowsersCastle.cpp
index 58aab3456..5c1e97236 100644
--- a/src/engine/courses/BowsersCastle.cpp
+++ b/src/engine/courses/BowsersCastle.cpp
@@ -6,7 +6,8 @@
#include "BowsersCastle.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/actors/AFinishline.h"
+#include "engine/vehicles/OBombKart.h"
#include "bowsers_castle_data.h"
extern "C" {
@@ -102,15 +103,40 @@ BowsersCastle::BowsersCastle() {
Props.Skybox.FloorTopLeft = {0, 0, 0};
}
+void BowsersCastle::Load() {
+ Course::Load();
+
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_bowsers_castle_addr));
+ func_80295C6C();
+ find_vtx_and_set_colours(segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07001350)), 0x32, 0, 0, 0);
+ D_8015F8E4 = -50.0f;
+}
+
void BowsersCastle::LoadTextures() {
dma_textures(gTextureShrub, 0x000003FFU, 0x00000800U);
}
void BowsersCastle::SpawnActors() {
+ gWorldInstance.AddActor(new AFinishline());
+
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));
}
+void BowsersCastle::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][150], 150, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][200], 200, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][260], 260, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][435], 435, 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 BowsersCastle::MinimapSettings() {
D_8018D2C0[0] = 265;
@@ -212,26 +238,12 @@ void BowsersCastle::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-void BowsersCastle::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(140, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(165, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(330, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(550, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(595, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void BowsersCastle::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void BowsersCastle::SetStaffGhost() {
-}
-
-void BowsersCastle::BeginPlay() { }
void BowsersCastle::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -269,13 +281,6 @@ void BowsersCastle::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, V
func_8003E6EC(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
-void BowsersCastle::GenerateCollision() {
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_bowsers_castle_addr));
- func_80295C6C();
- find_vtx_and_set_colours(segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07001350)), 0x32, 0, 0, 0);
- D_8015F8E4 = -50.0f;
-}
-
void BowsersCastle::Waypoints(Player* player, int8_t playerId) {
s16 waypoint = gNearestWaypointByPlayerId[playerId];
if ((waypoint >= 0x235) && (waypoint < 0x247)) {
@@ -290,4 +295,29 @@ void BowsersCastle::Waypoints(Player* player, int8_t playerId) {
}
}
+void BowsersCastle::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) {
+ if (gActiveScreenMode != SCREEN_MODE_1P) {
+ return;
+ }
+ if (pathCounter < 6) {
+ return;
+ }
+ if (pathCounter > 9) {
+ return;
+ }
+ if (pathCounter == 9) {
+ if (cameraRot < 0xA000) {
+ return;
+ }
+ if (cameraRot > 0xE000) {
+ return;
+ }
+ }
+ gSPDisplayList(gDisplayListHead++, (Gfx*)d_course_bowsers_castle_dl_9228);
+}
+
+void BowsersCastle::CreditsSpawnActors() {
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07001350), 0x32, 0, 0, 0);
+}
+
void BowsersCastle::Destroy() { }
diff --git a/src/engine/courses/BowsersCastle.h b/src/engine/courses/BowsersCastle.h
index e0ee8918d..bbbd4c75e 100644
--- a/src/engine/courses/BowsersCastle.h
+++ b/src/engine/courses/BowsersCastle.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
@@ -35,14 +37,12 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
virtual void Waypoints(Player*, int8_t) override;
+ virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection);
+ virtual void CreditsSpawnActors() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/ChocoMountain.cpp b/src/engine/courses/ChocoMountain.cpp
index bfb1950c3..bc88bf645 100644
--- a/src/engine/courses/ChocoMountain.cpp
+++ b/src/engine/courses/ChocoMountain.cpp
@@ -6,8 +6,9 @@
#include "ChocoMountain.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/vehicles/OBombKart.h"
#include "choco_mountain_data.h"
+#include "engine/actors/AFinishline.h"
extern "C" {
#include "main.h"
@@ -102,14 +103,62 @@ ChocoMountain::ChocoMountain() {
Props.Skybox.FloorTopLeft = {255, 255, 255};
}
+void ChocoMountain::Load() {
+ Course::Load();
+ D_800DC5BC = 1;
+ D_801625EC = 255;
+ D_801625F4 = 255;
+ D_801625F0 = 255;
+ D_802B87B0 = 0x3E3;
+ D_802B87B4 = 0x3E8;
+ D_802B87D4 = 0x71C;
+ D_802B87D0 = 0xE38;
+
+ // Spawn guardrail only for CC_50 and time trials.
+ if ((gCCSelection != CC_50) && (gModeSelection != TIME_TRIALS)) {
+ // d_course_choco_mountain_packed_dl_0
+ nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07000000)));
+ // d_course_choco_mountain_packed_dl_98
+ nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07000098)));
+ // d_course_choco_mountain_packed_dl_178
+ nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07000178)));
+ // d_course_choco_mountain_packed_dl_280
+ nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07000280)));
+ // d_course_choco_mountain_packed_dl_340
+ nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07000340)));
+ // d_course_choco_mountain_packed_dl_3C8
+ nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast<void*>(0x070003C8)));
+ }
+
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_choco_mountain_addr));
+ func_802B5CAC(0x238E, 0x31C7, D_8015F590);
+ func_80295C6C();
+ D_8015F8E4 = -80.0f;
+}
+
void ChocoMountain::LoadTextures() {
}
void ChocoMountain::SpawnActors() {
+ gWorldInstance.AddActor(new AFinishline());
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_choco_mountain_item_box_spawns));
spawn_falling_rocks((struct ActorSpawnData*)LOAD_ASSET_RAW((const char*)d_course_choco_mountain_falling_rock_spawns));
}
+void ChocoMountain::SpawnVehicles() {
+ if (gModeSelection == VERSUS) {
+ Vec3f pos = {0, 0, 0};
+
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][140], 140, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][165], 165, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][330], 330, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][550], 550, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][595], 595, 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 ChocoMountain::MinimapSettings() {
D_8018D2A0 = 0.022f;
@@ -165,26 +214,12 @@ void ChocoMountain::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-void ChocoMountain::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(140, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(165, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(330, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(550, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(595, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void ChocoMountain::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void ChocoMountain::SetStaffGhost() {
-}
-
-void ChocoMountain::BeginPlay() { }
void ChocoMountain::Render(struct UnkStruct_800DC5EC* arg0) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -242,36 +277,4 @@ void ChocoMountain::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, V
func_8003E37C(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
-void ChocoMountain::GenerateCollision() {
- D_800DC5BC = 1;
- D_801625EC = 255;
- D_801625F4 = 255;
- D_801625F0 = 255;
- D_802B87B0 = 0x3E3;
- D_802B87B4 = 0x3E8;
- D_802B87D4 = 0x71C;
- D_802B87D0 = 0xE38;
-
- // Spawn guardrail only for CC_50 and time trials.
- if ((gCCSelection != CC_50) && (gModeSelection != TIME_TRIALS)) {
- // d_course_choco_mountain_packed_dl_0
- nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07000000)));
- // d_course_choco_mountain_packed_dl_98
- nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07000098)));
- // d_course_choco_mountain_packed_dl_178
- nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07000178)));
- // d_course_choco_mountain_packed_dl_280
- nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07000280)));
- // d_course_choco_mountain_packed_dl_340
- nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07000340)));
- // d_course_choco_mountain_packed_dl_3C8
- nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast<void*>(0x070003C8)));
- }
-
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_choco_mountain_addr));
- func_802B5CAC(0x238E, 0x31C7, D_8015F590);
- func_80295C6C();
- D_8015F8E4 = -80.0f;
-}
-
void ChocoMountain::Destroy() { }
diff --git a/src/engine/courses/ChocoMountain.h b/src/engine/courses/ChocoMountain.h
index c45d6ff1f..718b40202 100644
--- a/src/engine/courses/ChocoMountain.h
+++ b/src/engine/courses/ChocoMountain.h
@@ -24,22 +24,19 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
- //virtual void InitClouds() override;
+ virtual void SpawnVehicles() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/Course.cpp b/src/engine/courses/Course.cpp
index f844adcdf..bdec26404 100644
--- a/src/engine/courses/Course.cpp
+++ b/src/engine/courses/Course.cpp
@@ -17,6 +17,8 @@ extern "C" {
#include "save.h"
#include "staff_ghosts.h"
#include "Engine.h"
+ #include "code_800029B0.h"
+ #include "render_courses.h"
extern StaffGhost* d_mario_raceway_staff_ghost;
}
@@ -76,6 +78,8 @@ Course::Course() {
void Course::Load(Vtx* vtx, Gfx* gfx) {
gSegmentTable[4] = reinterpret_cast<uintptr_t>(&vtx[0]);
gSegmentTable[7] = reinterpret_cast<uintptr_t>(&gfx[0]);
+
+ Course::Init();
}
void Course::Load() {
@@ -86,7 +90,6 @@ void Course::Load() {
// Convert course vtx to vtx
Vtx* vtx = reinterpret_cast<Vtx*>(allocate_memory(vtxSize));
gSegmentTable[4] = reinterpret_cast<uintptr_t>(&vtx[0]);
- printf("\nVtxsize: 0x%X\n\n",vtxSize);
func_802A86A8(reinterpret_cast<CourseVtx*>(LOAD_ASSET_RAW(this->vtx)), vtx, vtxSize / sizeof(Vtx));
// Load and allocate memory for course textures
@@ -117,6 +120,28 @@ void Course::Load() {
assert(gfx != NULL);
gSegmentTable[7] = reinterpret_cast<uintptr_t>(&gfx[0]);
displaylist_unpack(reinterpret_cast<uintptr_t *>(gfx), reinterpret_cast<uintptr_t>(packed), 0);
+
+ Course::Init();
+}
+
+void Course::Init() {
+ gNumActors = 0;
+ gCourseMinX = 0;
+ gCourseMinY = 0;
+ gCourseMinZ = 0;
+
+ gCourseMaxX = 0;
+ gCourseMaxY = 0;
+ gCourseMaxZ = 0;
+
+ D_8015F59C = 0;
+ D_8015F5A0 = 0;
+ func_80295D6C();
+ D_8015F58C = 0;
+ gCollisionMeshCount = 0;
+ gCollisionMesh = (CollisionTriangle*) gNextFreeMemoryAddress;
+ D_800DC5BC = 0;
+ D_800DC5C8 = 0;
}
void Course::LoadTextures() { }
@@ -172,7 +197,7 @@ void Course::SomeSounds() {
}
-void Course::SetCourseVtxColours() {
+void Course::CreditsSpawnActors() {
}
@@ -195,9 +220,6 @@ void Course::SetStaffGhost() {
D_80162DF4 = 1;
}
-void Course::SpawnBombKarts() {
-}
-
void Course::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = gNearestWaypointByPlayerId[playerId];
if (player->nearestWaypointId < 0) {
@@ -208,12 +230,11 @@ void Course::Waypoints(Player* player, int8_t playerId) {
void Course::SpawnVehicles() {}
void Course::UpdateVehicles() {}
-void Course::BeginPlay() {}
void Course::Render(struct UnkStruct_800DC5EC* arg0) {}
void Course::RenderCredits() {}
void Course::Collision() {}
-void Course::GenerateCollision() {}
-void Course::Water() {}
+void Course::ScrollingTextures() {}
+void Course::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) {}
void Course::Destroy() { }
diff --git a/src/engine/courses/Course.h b/src/engine/courses/Course.h
index 00eb54f46..20fd553c0 100644
--- a/src/engine/courses/Course.h
+++ b/src/engine/courses/Course.h
@@ -100,22 +100,22 @@ public:
virtual void UpdateCourseObjects();
virtual void RenderCourseObjects(s32 cameraId);
virtual void SomeSounds();
- virtual void SetCourseVtxColours();
+ virtual void CreditsSpawnActors();
virtual void WhatDoesThisDo(Player*, int8_t);
virtual void WhatDoesThisDoAI(Player*, int8_t);
virtual void MinimapFinishlinePosition();
virtual void SetStaffGhost();
- virtual void SpawnBombKarts();
- virtual void BeginPlay();
virtual void Render(struct UnkStruct_800DC5EC*);
virtual void RenderCredits();
virtual void SpawnVehicles();
virtual void UpdateVehicles();
virtual void Waypoints(Player* player, int8_t playerId);
virtual void Collision();
- virtual void GenerateCollision();
- virtual void Water();
+ virtual void ScrollingTextures();
+ virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection);
virtual void Destroy();
+private:
+ void Init();
};
#endif
diff --git a/src/engine/courses/DKJungle.cpp b/src/engine/courses/DKJungle.cpp
index bc8257548..4c3d6797c 100644
--- a/src/engine/courses/DKJungle.cpp
+++ b/src/engine/courses/DKJungle.cpp
@@ -6,7 +6,8 @@
#include "DKJungle.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/actors/AFinishline.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/dks_jungle_parkway_data.h"
#include "engine/vehicles/Utils.h"
@@ -105,6 +106,16 @@ DKJungle::DKJungle() {
Props.Skybox.FloorTopLeft = {22, 145, 22};
}
+void DKJungle::Load() {
+ Course::Load();
+
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_dks_jungle_parkway_addr));
+ func_80295C6C();
+ D_8015F8E4 = -475.0f;
+ // d_course_dks_jungle_parkway_packed_dl_3FA8
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07003FA8), 120, 255, 255, 255);
+}
+
void DKJungle::LoadTextures() {
dma_textures(gTextureDksJungleParkwayKiwanoFruit1, 0x0000032FU, 0x00000400U);
dma_textures(gTextureDksJungleParkwayKiwanoFruit2, 0x00000369U, 0x00000400U);
@@ -112,6 +123,8 @@ void DKJungle::LoadTextures() {
}
void DKJungle::SpawnActors() {
+ gWorldInstance.AddActor(new AFinishline());
+
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_dks_jungle_parkway_item_box_spawns));
init_kiwano_fruit();
func_80298D10();
@@ -193,25 +206,12 @@ void DKJungle::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-void DKJungle::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(40, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(100, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(265, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(285, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(420, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void DKJungle::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void DKJungle::SetStaffGhost() {}
-
-void DKJungle::BeginPlay() { }
void DKJungle::Render(struct UnkStruct_800DC5EC* arg0) {
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
func_802B5D64(&D_800DC610[1], D_802B87D4, D_802B87D0, 1);
@@ -248,15 +248,21 @@ void DKJungle::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f
void DKJungle::SpawnVehicles() {
generate_ferry_waypoints();
- gWorldInstance.AddBoat(1.6666666f, 0);
-}
+ // 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);
-void DKJungle::GenerateCollision() {
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_dks_jungle_parkway_addr));
- func_80295C6C();
- D_8015F8E4 = -475.0f;
- // d_course_dks_jungle_parkway_packed_dl_3FA8
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07003FA8), 120, 255, 255, 255);
+ 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][190], 190, 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);
+ }
}
void DKJungle::Waypoints(Player* player, int8_t playerId) {
@@ -271,4 +277,188 @@ void DKJungle::Waypoints(Player* player, int8_t playerId) {
}
}
+void DKJungle::ScrollingTextures() {
+ D_802B87BC += 2;
+ if (D_802B87BC > 255) {
+ D_802B87BC = 0;
+ }
+ // d_course_dks_jungle_parkway_packed_dl_3DD0
+ find_and_set_tile_size((uintptr_t) segmented_gfx_to_virtual((void*)0x07003DD0), 0, D_802B87BC);
+ // d_course_dks_jungle_parkway_packed_dl_3E40
+ find_and_set_tile_size((uintptr_t) segmented_gfx_to_virtual((void*)0x07003E40), 0, D_802B87BC);
+ // d_course_dks_jungle_parkway_packed_dl_3EB0
+ find_and_set_tile_size((uintptr_t) segmented_gfx_to_virtual((void*)0x07003EB0), 0, D_802B87BC);
+ // d_course_dks_jungle_parkway_packed_dl_3F30
+ find_and_set_tile_size((uintptr_t) segmented_gfx_to_virtual((void*)0x07003F30), 0, D_802B87BC);
+ // d_course_dks_jungle_parkway_packed_dl_36A8
+ find_and_set_tile_size((uintptr_t) segmented_gfx_to_virtual((void*)0x070036A8), 0, D_802B87BC);
+ D_802B87C4 -= 20;
+ if (D_802B87C4 < 0) {
+ D_802B87C4 = 0xFF;
+ }
+ // d_course_dks_jungle_parkway_packed_dl_9880
+ find_and_set_tile_size((uintptr_t) segmented_gfx_to_virtual((void*)0x07009880), 0, D_802B87C4);
+ evaluate_collision_players_palm_trees();
+}
+
+void DKJungle::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) {
+ Mat4 matrix;
+ gDPPipeSync(gDisplayListHead++);
+ gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
+ gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
+ gDPSetBlendMask(gDisplayListHead++, 0xFF);
+ gDPSetTextureFilter(gDisplayListHead++, G_TF_BILERP);
+ gDPSetTexturePersp(gDisplayListHead++, G_TP_PERSP);
+
+ mtxf_identity(matrix);
+ render_set_position(matrix, 0);
+
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
+ gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_XLU_INTER, G_RM_NOOP2);
+
+ if (pathCounter < 17) {
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
+ // d_course_dks_jungle_parkway_packed_dl_3E40
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003E40));
+ // d_course_dks_jungle_parkway_packed_dl_3EB0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003EB0));
+ if ((pathCounter >= 6) && (pathCounter < 13)) {
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
+ // d_course_dks_jungle_parkway_packed_dl_3DD0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003DD0));
+ }
+ } else if ((pathCounter == 21) || (pathCounter == 22)) {
+ if (playerDirection == 3) {
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
+ // d_course_dks_jungle_parkway_packed_dl_36A8
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x070036A8));
+ }
+ if ((playerDirection == 1) || (playerDirection == 0)) {
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
+ // d_course_dks_jungle_parkway_packed_dl_36A8
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x070036A8));
+ } else {
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
+ // d_course_dks_jungle_parkway_packed_dl_3F30
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003F30));
+ // d_course_dks_jungle_parkway_packed_dl_36A8
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x070036A8));
+ }
+ } else if (pathCounter == 24) {
+ if ((playerDirection == 0) || (playerDirection == 3)) {
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
+ // d_course_dks_jungle_parkway_packed_dl_36A8
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x070036A8));
+ }
+ } else if (pathCounter == 23) {
+ if (playerDirection == 3) {
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
+ // d_course_dks_jungle_parkway_packed_dl_36A8
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x070036A8));
+ } else if (playerDirection == 0) {
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
+ // d_course_dks_jungle_parkway_packed_dl_36A8
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x070036A8));
+ }
+ }
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
+ switch (pathCounter) {
+ case 5:
+ if (playerDirection != 3) {
+ // d_course_dks_jungle_parkway_packed_dl_3DD0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003DD0));
+ }
+ break;
+ case 17:
+ switch (playerDirection) {
+ case 0:
+ // d_course_dks_jungle_parkway_packed_dl_3E40
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003E40));
+ // d_course_dks_jungle_parkway_packed_dl_3EB0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003EB0));
+ break;
+ case 1:
+ // d_course_dks_jungle_parkway_packed_dl_3DD0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003DD0));
+ // d_course_dks_jungle_parkway_packed_dl_3E40
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003E40));
+ // d_course_dks_jungle_parkway_packed_dl_3EB0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003EB0));
+ break;
+ case 2:
+ // d_course_dks_jungle_parkway_packed_dl_
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003E40));
+ // d_course_dks_jungle_parkway_packed_dl_3EB0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003EB0));
+ // d_course_dks_jungle_parkway_packed_dl_3F30
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003F30));
+ break;
+ case 3:
+ // d_course_dks_jungle_parkway_packed_dl_3EB0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003EB0));
+ // d_course_dks_jungle_parkway_packed_dl_3F30
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003F30));
+ break;
+ }
+ break;
+ case 18:
+ switch (playerDirection) {
+ case 0:
+ // d_course_dks_jungle_parkway_packed_dl_3E40
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003E40));
+ // d_course_dks_jungle_parkway_packed_dl_3EB0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003EB0));
+ break;
+ case 1:
+ // d_course_dks_jungle_parkway_packed_dl_3DD0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003DD0));
+ // d_course_dks_jungle_parkway_packed_dl_3E40
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003E40));
+ // d_course_dks_jungle_parkway_packed_dl_3EB0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003EB0));
+ break;
+ case 2:
+ // d_course_dks_jungle_parkway_packed_dl_3E40
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003E40));
+ // d_course_dks_jungle_parkway_packed_dl_3EB0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003EB0));
+ break;
+ }
+ break;
+ case 21:
+ if ((playerDirection == 0) || (playerDirection == 1)) {
+ // d_course_dks_jungle_parkway_packed_dl_3E40
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003E40));
+ // d_course_dks_jungle_parkway_packed_dl_3EB0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003EB0));
+ // d_course_dks_jungle_parkway_packed_dl_3F30
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003F30));
+ } else {
+ // d_course_dks_jungle_parkway_packed_dl_3EB0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003EB0));
+ }
+ break;
+ case 22:
+ if (playerDirection == 0) {
+ // d_course_dks_jungle_parkway_packed_dl_3F30
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003F30));
+ }
+ break;
+ case 23:
+ if (playerDirection != 1) {
+ // d_course_dks_jungle_parkway_packed_dl_3F30
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07003F30));
+ }
+ break;
+ }
+ gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 1, 1, G_OFF);
+ gDPSetAlphaCompare(gDisplayListHead++, G_AC_NONE);
+ gDPPipeSync(gDisplayListHead++);
+}
+
+void DKJungle::CreditsSpawnActors() {
+ // d_course_dks_jungle_parkway_packed_dl_3FA8
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07003FA8), 0x78, 0xFF, 0xFF, 0xFF);
+}
+
void DKJungle::Destroy() { }
diff --git a/src/engine/courses/DKJungle.h b/src/engine/courses/DKJungle.h
index bbe4e1cbf..389213c1f 100644
--- a/src/engine/courses/DKJungle.h
+++ b/src/engine/courses/DKJungle.h
@@ -24,6 +24,7 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
//virtual void InitClouds() override;
@@ -35,15 +36,14 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void SpawnVehicles() override;
virtual void Collision() override;
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
+ virtual void ScrollingTextures() override;
+ virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override;
+ virtual void CreditsSpawnActors() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/DoubleDeck.cpp b/src/engine/courses/DoubleDeck.cpp
index 43b4b47c7..7d07cdc43 100644
--- a/src/engine/courses/DoubleDeck.cpp
+++ b/src/engine/courses/DoubleDeck.cpp
@@ -6,7 +6,7 @@
#include "DoubleDeck.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/double_deck_data.h"
extern "C" {
@@ -101,10 +101,34 @@ DoubleDeck::DoubleDeck() {
Props.Skybox.FloorTopLeft = {255, 224, 240};
}
+void DoubleDeck::Load() {
+ Course::Load();
+
+ generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000738), 1);
+ func_80295C6C();
+ D_8015F8E4 = gCourseMinY - 10.0f;
+}
+
void DoubleDeck::LoadTextures() {
}
-void DoubleDeck::SpawnActors() {}
+void DoubleDeck::SpawnActors() {
+ spawn_all_item_boxes((ActorSpawnData*)LOAD_ASSET_RAW(d_course_double_deck_item_box_spawns));
+}
+
+void DoubleDeck::SpawnVehicles() {
+ if (gModeSelection == VERSUS) {
+ Vec3f pos = {0, 0, 0};
+
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][20], 20, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][40], 40, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][60], 60, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][80], 80, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][100], 100, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][120], 120, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][140], 140, 0, 1.0f);
+ }
+}
// Likely sets minimap boundaries
void DoubleDeck::MinimapSettings() {
@@ -121,17 +145,12 @@ void DoubleDeck::WhatDoesThisDo(Player* player, int8_t playerId) {}
void DoubleDeck::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-void DoubleDeck::SpawnBombKarts() {}
-
// Positions the finishline on the minimap
void DoubleDeck::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void DoubleDeck::SetStaffGhost() {}
-
-void DoubleDeck::BeginPlay() { }
void DoubleDeck::Render(struct UnkStruct_800DC5EC* arg0) {
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
@@ -147,12 +166,6 @@ void DoubleDeck::RenderCredits() {}
void DoubleDeck::Collision() {}
-void DoubleDeck::GenerateCollision() {
- generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000738), 1);
- func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
-}
-
void DoubleDeck::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = 0;
}
diff --git a/src/engine/courses/DoubleDeck.h b/src/engine/courses/DoubleDeck.h
index 5d453742e..bb1a8f98c 100644
--- a/src/engine/courses/DoubleDeck.h
+++ b/src/engine/courses/DoubleDeck.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
@@ -33,13 +35,9 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/FrappeSnowland.cpp b/src/engine/courses/FrappeSnowland.cpp
index 8236c345a..90fa51e6c 100644
--- a/src/engine/courses/FrappeSnowland.cpp
+++ b/src/engine/courses/FrappeSnowland.cpp
@@ -6,7 +6,8 @@
#include "FrappeSnowland.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/actors/AFinishline.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/frappe_snowland_data.h"
#include "assets/boo_frames.h"
@@ -103,16 +104,40 @@ FrappeSnowland::FrappeSnowland() {
Props.Skybox.FloorTopLeft = {0, 99, 164};
}
+void FrappeSnowland::Load() {
+ Course::Load();
+
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_frappe_snowland_addr));
+ func_80295C6C();
+ D_8015F8E4 = -50.0f;
+}
+
void FrappeSnowland::LoadTextures() {
dma_textures(gTextureFrappeSnowlandTreeLeft, 0x00000454U, 0x00000800U);
dma_textures(gTextureFrappeSnowlandTreeRight, 0x00000432U, 0x00000800U);
}
void FrappeSnowland::SpawnActors() {
+ gWorldInstance.AddActor(new AFinishline());
+
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_frappe_snowland_tree_spawns));
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_frappe_snowland_item_box_spawns));
}
+void FrappeSnowland::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][290], 290, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][350], 350, 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);
+ }
+}
+
void FrappeSnowland::InitClouds() {
s32 var_s0;
s32 var_s4;
@@ -187,27 +212,12 @@ void FrappeSnowland::WhatDoesThisDo(Player* player, int8_t playerId) {}
void FrappeSnowland::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-void FrappeSnowland::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(140, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(165, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(330, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(550, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(595, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void FrappeSnowland::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void FrappeSnowland::SetStaffGhost() {
-}
-
-void FrappeSnowland::BeginPlay() { }
-
void FrappeSnowland::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -231,12 +241,6 @@ void FrappeSnowland::RenderCredits() {
void FrappeSnowland::Collision() {}
-void FrappeSnowland::GenerateCollision() {
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_frappe_snowland_addr));
- func_80295C6C();
- D_8015F8E4 = -50.0f;
-}
-
void FrappeSnowland::Waypoints(Player* player, int8_t playerId) {
s16 waypoint = gNearestWaypointByPlayerId[playerId];
@@ -250,6 +254,6 @@ void FrappeSnowland::Waypoints(Player* player, int8_t playerId) {
}
}
-void FrappeSnowland::Water() {}
+void FrappeSnowland::ScrollingTextures() {}
void FrappeSnowland::Destroy() {}
diff --git a/src/engine/courses/FrappeSnowland.h b/src/engine/courses/FrappeSnowland.h
index f01943015..5c53dafae 100644
--- a/src/engine/courses/FrappeSnowland.h
+++ b/src/engine/courses/FrappeSnowland.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
virtual void InitClouds() override;
virtual void UpdateClouds(s32 sp1C, Camera* camera) override;
virtual void MinimapSettings() override;
@@ -36,14 +38,10 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
- virtual void Water() override;
+ virtual void ScrollingTextures() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/KalimariDesert.cpp b/src/engine/courses/KalimariDesert.cpp
index c88e52f9a..df6b4237d 100644
--- a/src/engine/courses/KalimariDesert.cpp
+++ b/src/engine/courses/KalimariDesert.cpp
@@ -6,7 +6,8 @@
#include "KalimariDesert.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/actors/AFinishline.h"
+#include "engine/vehicles/OBombKart.h"
#include "kalimari_desert_data.h"
#include "engine/vehicles/Utils.h"
@@ -103,6 +104,14 @@ KalimariDesert::KalimariDesert() {
Props.Skybox.FloorTopLeft = {255, 192, 0};
}
+void KalimariDesert::Load() {
+ Course::Load();
+
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_kalimari_desert_addr));
+ func_80295C6C();
+ D_8015F8E4 = gCourseMinY - 10.0f;
+}
+
void KalimariDesert::LoadTextures() {
dma_textures(gTextureCactus1Left, 0x0000033EU, 0x00000800U);
dma_textures(gTextureCactus1Right, 0x000002FBU, 0x00000800U);
@@ -117,6 +126,8 @@ void KalimariDesert::SpawnActors() {
Vec3f velocity = { 0.0f, 0.0f, 0.0f };
Vec3s rotation = { 0, 0, 0 };
+ gWorldInstance.AddActor(new AFinishline());
+
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_kalimari_desert_cactus_spawn));
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_kalimari_desert_item_box_spawns));
@@ -127,24 +138,24 @@ void KalimariDesert::SpawnActors() {
vec3f_set(position, -1680.0f, 2.0f, 35.0f);
position[0] *= gCourseDirection;
- rrxing = (struct RailroadCrossing*) &gActorList[add_actor_to_empty_slot(position, rotation, velocity,
- ACTOR_RAILROAD_CROSSING)];
+ rrxing = (struct RailroadCrossing*) GET_ACTOR(add_actor_to_empty_slot(position, rotation, velocity,
+ ACTOR_RAILROAD_CROSSING));
rrxing->crossingTrigger = crossing2;
vec3f_set(position, -1600.0f, 2.0f, 35.0f);
position[0] *= gCourseDirection;
- rrxing = (struct RailroadCrossing*) &gActorList[add_actor_to_empty_slot(position, rotation, velocity,
- ACTOR_RAILROAD_CROSSING)];
+ rrxing = (struct RailroadCrossing*) GET_ACTOR(add_actor_to_empty_slot(position, rotation, velocity,
+ ACTOR_RAILROAD_CROSSING));
rrxing->crossingTrigger = crossing2;
vec3s_set(rotation, 0, -0x2000, 0);
vec3f_set(position, -2459.0f, 2.0f, 2263.0f);
position[0] *= gCourseDirection;
- rrxing = (struct RailroadCrossing*) &gActorList[add_actor_to_empty_slot(position, rotation, velocity,
- ACTOR_RAILROAD_CROSSING)];
+ rrxing = (struct RailroadCrossing*) GET_ACTOR(add_actor_to_empty_slot(position, rotation, velocity,
+ ACTOR_RAILROAD_CROSSING));
rrxing->crossingTrigger = crossing1;
vec3f_set(position, -2467.0f, 2.0f, 2375.0f);
position[0] *= gCourseDirection;
- rrxing = (struct RailroadCrossing*) &gActorList[add_actor_to_empty_slot(position, rotation, velocity,
- ACTOR_RAILROAD_CROSSING)];
+ rrxing = (struct RailroadCrossing*) GET_ACTOR(add_actor_to_empty_slot(position, rotation, velocity,
+ ACTOR_RAILROAD_CROSSING));
rrxing->crossingTrigger = crossing1;
}
@@ -181,24 +192,12 @@ void KalimariDesert::WhatDoesThisDo(Player* player, int8_t playerId) {}
void KalimariDesert::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-void KalimariDesert::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(140, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(165, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(330, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(550, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(595, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void KalimariDesert::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void KalimariDesert::SetStaffGhost() {}
-
void KalimariDesert::SpawnVehicles() {
generate_train_waypoints();
@@ -209,11 +208,22 @@ void KalimariDesert::SpawnVehicles() {
for (size_t i = 0; i < numTrains; ++i) {
uint32_t waypoint = CalculateWaypointDistribution(i, numTrains, gVehicle2DWaypointLength, centerWaypoint);
- gWorldInstance.AddTrain(5, 5.0f, waypoint);
+ gWorldInstance.AddTrain(5, 2.5f, waypoint);
+ }
+
+ 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][138], 138, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][280], 280, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][404], 404, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][510], 510, 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);
}
}
-void KalimariDesert::BeginPlay() { }
void KalimariDesert::Render(struct UnkStruct_800DC5EC* arg0) {
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
@@ -253,10 +263,4 @@ void KalimariDesert::RenderCredits() {
void KalimariDesert::Collision() {}
-void KalimariDesert::GenerateCollision() {
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_kalimari_desert_addr));
- func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
-}
-
void KalimariDesert::Destroy() { }
diff --git a/src/engine/courses/KalimariDesert.h b/src/engine/courses/KalimariDesert.h
index 337be914e..8c2d9a4d8 100644
--- a/src/engine/courses/KalimariDesert.h
+++ b/src/engine/courses/KalimariDesert.h
@@ -24,6 +24,7 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
virtual void MinimapSettings() override;
@@ -32,13 +33,9 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void SpawnVehicles() override;
virtual void Collision() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/KoopaTroopaBeach.cpp b/src/engine/courses/KoopaTroopaBeach.cpp
index fc0419984..66bf99005 100644
--- a/src/engine/courses/KoopaTroopaBeach.cpp
+++ b/src/engine/courses/KoopaTroopaBeach.cpp
@@ -6,7 +6,8 @@
#include "KoopaTroopaBeach.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/actors/AFinishline.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/koopa_troopa_beach_data.h"
extern "C" {
@@ -103,15 +104,42 @@ KoopaTroopaBeach::KoopaTroopaBeach() {
Props.Skybox.FloorTopLeft = {48, 152, 120};
}
+void KoopaTroopaBeach::Load() {
+ Course::Load();
+
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_addr));
+ func_80295C6C();
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x0700ADE0), -0x6A, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x0700A540), -0x6A, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07009E70), -0x6A, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000358), -0x6A, 255, 255, 255);
+}
+
void KoopaTroopaBeach::LoadTextures() {
}
void KoopaTroopaBeach::SpawnActors() {
+ gWorldInstance.AddActor(new AFinishline());
+
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));
}
+void KoopaTroopaBeach::SpawnVehicles() {
+ if (gModeSelection == VERSUS) {
+ Vec3f pos = {0, 0, 0};
+
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][60], 60, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][120], 120, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][200], 200, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][280], 280, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][435], 435, 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 KoopaTroopaBeach::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust3, 0x3C8U, 0x1000));
@@ -180,27 +208,12 @@ void KoopaTroopaBeach::WhatDoesThisDo(Player* player, int8_t playerId) {}
void KoopaTroopaBeach::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-void KoopaTroopaBeach::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(140, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(165, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(330, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(550, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(595, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void KoopaTroopaBeach::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void KoopaTroopaBeach::SetStaffGhost() {
-}
-
-void KoopaTroopaBeach::BeginPlay() { }
-
void KoopaTroopaBeach::Render(struct UnkStruct_800DC5EC* arg0) {
gDPPipeSync(gDisplayListHead++);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
@@ -237,16 +250,7 @@ void KoopaTroopaBeach::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2
func_8003E37C(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
-void KoopaTroopaBeach::GenerateCollision() {
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_addr));
- func_80295C6C();
- find_vtx_and_set_colours(segmented_gfx_to_virtual(reinterpret_cast<void*>(0x0700ADE0)), -0x6A, 255, 255, 255);
- find_vtx_and_set_colours(segmented_gfx_to_virtual(reinterpret_cast<void*>(0x0700A540)), -0x6A, 255, 255, 255);
- find_vtx_and_set_colours(segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07009E70)), -0x6A, 255, 255, 255);
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000358), -0x6A, 255, 255, 255);
-}
-
-void KoopaTroopaBeach::Water() {
+void KoopaTroopaBeach::ScrollingTextures() {
// clang-format off
if (D_8015F8E8 < 0.0f) {
if (D_8015F8E4 < -20.0f) { D_8015F8E8 *= -1.0f; }
@@ -281,4 +285,45 @@ void KoopaTroopaBeach::Water() {
}
+void KoopaTroopaBeach::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) {
+ Mat4 matrix;
+ Vec3f vector;
+
+ gDPPipeSync(gDisplayListHead++);
+ gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
+ gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
+ gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_XLU_INTER, G_RM_NOOP2);
+ gDPSetBlendMask(gDisplayListHead++, 0xFF);
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
+
+ switch (pathCounter) {
+ case 22:
+ case 23:
+ case 29:
+ case 30:
+ case 31:
+ case 37:
+ gSPClearGeometryMode(gDisplayListHead++, G_CULL_BACK);
+ // d_course_koopa_troopa_beach_packed_dl_9E70
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07009E70));
+ gSPSetGeometryMode(gDisplayListHead++, G_CULL_BACK);
+ break;
+ }
+ vector[0] = 0.0f;
+ vector[1] = D_8015F8E4;
+ vector[2] = 0.0f;
+ mtxf_translate(matrix, vector);
+ render_set_position(matrix, 0);
+
+ gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_XLU_INTER, G_RM_NOOP2);
+ gDPSetBlendMask(gDisplayListHead++, 0xFF);
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
+ gSPClearGeometryMode(gDisplayListHead++, G_CULL_BACK);
+ render_course_segments((const char**)koopa_troopa_beach_dls2, screen);
+ gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 1, 1, G_OFF);
+ gSPSetGeometryMode(gDisplayListHead++, G_CULL_BACK);
+ gDPSetAlphaCompare(gDisplayListHead++, G_AC_NONE);
+ gDPPipeSync(gDisplayListHead++);
+}
+
void KoopaTroopaBeach::Destroy() {}
diff --git a/src/engine/courses/KoopaTroopaBeach.h b/src/engine/courses/KoopaTroopaBeach.h
index b930bbd95..4dc51313e 100644
--- a/src/engine/courses/KoopaTroopaBeach.h
+++ b/src/engine/courses/KoopaTroopaBeach.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
@@ -34,14 +36,11 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
- virtual void Water() override;
+ virtual void ScrollingTextures() override;
+ virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/LuigiRaceway.cpp b/src/engine/courses/LuigiRaceway.cpp
index 2f1ff2751..f9a9de13a 100644
--- a/src/engine/courses/LuigiRaceway.cpp
+++ b/src/engine/courses/LuigiRaceway.cpp
@@ -6,8 +6,9 @@
#include "LuigiRaceway.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/luigi_raceway_data.h"
+#include "engine/actors/AFinishline.h"
extern "C" {
#include "main.h"
@@ -30,6 +31,8 @@ extern "C" {
#include "collision.h"
#include "code_8003DC40.h"
#include "memory.h"
+ #include "courses/staff_ghost_data.h"
+ #include "framebuffer_effects.h"
extern const char *luigi_raceway_dls[];
extern s16 currentScreenSection;
}
@@ -103,16 +106,39 @@ LuigiRaceway::LuigiRaceway() {
Props.Skybox.FloorTopLeft = {216, 232, 248};
}
+void LuigiRaceway::Load() {
+ Course::Load();
+
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_luigi_raceway_addr));
+ func_80295C6C();
+ D_8015F8E4 = gCourseMinY - 10.0f;
+}
+
void LuigiRaceway::LoadTextures() {
dma_textures(gTextureTrees5Left, 0x000003E8U, 0x00000800U);
dma_textures(gTextureTrees5Right, 0x000003E8U, 0x00000800U);
}
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));
}
+void LuigiRaceway::SpawnVehicles() {
+ if (gModeSelection == VERSUS) {
+ Vec3f pos = {0, 0, 0};
+
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][50], 50, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][200], 200, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][305], 305, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][440], 440, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][515], 515, 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 LuigiRaceway::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust2, 0x4F4U, 0xC00));
@@ -187,16 +213,6 @@ void LuigiRaceway::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-void LuigiRaceway::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(40, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(100, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(265, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(285, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(420, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void LuigiRaceway::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
@@ -216,8 +232,6 @@ void LuigiRaceway::SetStaffGhost() {
D_80162DE4 = 1;
}
-void LuigiRaceway::BeginPlay() {}
-
void LuigiRaceway::Render(struct UnkStruct_800DC5EC* arg0) {
UNUSED s32 pad;
u16 sp22 = (u16) arg0->pathCounter;
@@ -264,9 +278,8 @@ void LuigiRaceway::Render(struct UnkStruct_800DC5EC* arg0) {
currentScreenSection = 0;
}
- u16* fb = (u16*) gSegmentTable[5] + 0xF800;
-
- // FB_WriteFramebufferSliceToCPU(gDisplayListHead, fb, true);
+ uintptr_t fb = (uintptr_t) gSegmentTable[5] + 0xF800;
+ FB_WriteFramebufferSliceToCPU(gDisplayListHead, (void*)fb, true);
// FB_DrawFromFramebuffer(gDisplayListHead, 0, fb, true);
// FB_CopyToFramebuffer(gDisplayListHead, 0, fb, false, NULL);
/**
@@ -330,10 +343,4 @@ void LuigiRaceway::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Ve
func_8003E9EC(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
-void LuigiRaceway::GenerateCollision() {
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_luigi_raceway_addr));
- func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
-}
-
void LuigiRaceway::Destroy() { }
diff --git a/src/engine/courses/LuigiRaceway.h b/src/engine/courses/LuigiRaceway.h
index 0f48c40ab..eb32e6c78 100644
--- a/src/engine/courses/LuigiRaceway.h
+++ b/src/engine/courses/LuigiRaceway.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
@@ -35,12 +37,9 @@ public:
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/MarioRaceway.cpp b/src/engine/courses/MarioRaceway.cpp
index 2900ad36e..f93b76762 100644
--- a/src/engine/courses/MarioRaceway.cpp
+++ b/src/engine/courses/MarioRaceway.cpp
@@ -6,7 +6,8 @@
#include "MarioRaceway.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/actors/AFinishline.h"
+#include "engine/vehicles/OBombKart.h"
extern "C" {
#include "main.h"
@@ -29,6 +30,7 @@ extern "C" {
#include "mario_raceway_data.h"
#include "collision.h"
#include "memory.h"
+ #include "courses/staff_ghost_data.h"
extern const char *mario_raceway_dls[];
}
@@ -102,6 +104,23 @@ MarioRaceway::MarioRaceway() {
Props.Skybox.FloorTopLeft = {0, 0, 0};
}
+void MarioRaceway::Load() {
+ Course::Load();
+
+ generate_collision_mesh_with_defaults(segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07001140)));
+ if (gScreenModeSelection == SCREEN_MODE_1P) {
+ // d_course_mario_raceway_packed_dl_8E8
+ generate_collision_mesh_with_defaults(segmented_gfx_to_virtual(reinterpret_cast<void*>(0x070008E8)));
+ } else {
+ // d_course_mario_raceway_packed_dl_2D68
+ generate_collision_mesh_with_defaults(segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07002D68)));
+ }
+
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_mario_raceway_addr));
+ func_80295C6C();
+ D_8015F8E4 = gCourseMinY - 10.0f;
+}
+
void MarioRaceway::LoadTextures() {
dma_textures(gTextureTrees1, 0x0000035BU, 0x00000800U);
D_802BA058 = dma_textures(gTexturePiranhaPlant1, 0x000003E8U, 0x00000800U);
@@ -120,6 +139,9 @@ void MarioRaceway::SpawnActors() {
Vec3f position;
Vec3f velocity = { 0.0f, 0.0f, 0.0f };
Vec3s rotation = { 0, 0, 0 };
+
+ gWorldInstance.AddActor(new AFinishline());
+
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_mario_raceway_tree_spawns));
spawn_piranha_plants((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_mario_raceway_piranha_plant_spawns));
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_mario_raceway_item_box_spawns));
@@ -128,8 +150,21 @@ void MarioRaceway::SpawnActors() {
add_actor_to_empty_slot(position, rotation, velocity, ACTOR_MARIO_SIGN);
vec3f_set(position, 2520.0f, 0.0f, 1240.0f);
position[0] *= gCourseDirection;
- actor = &gActorList[add_actor_to_empty_slot(position, rotation, velocity, ACTOR_MARIO_SIGN)];
- actor->flags |= 0x4000;
+ add_actor_to_empty_slot(position, rotation, velocity, ACTOR_MARIO_SIGN);
+}
+
+void MarioRaceway::SpawnVehicles() {
+ if (gModeSelection == VERSUS) {
+ Vec3f pos = {0, 0, 0};
+
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][40], 40, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][100], 100, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][265], 265, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][285], 285, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][420], 420, 1, 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
@@ -192,16 +227,6 @@ void MarioRaceway::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-void MarioRaceway::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(40, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(100, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(265, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(285, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(420, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void MarioRaceway::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
@@ -221,7 +246,6 @@ void MarioRaceway::SetStaffGhost() {
D_80162DE4 = 0;
}
-void MarioRaceway::BeginPlay() { }
void MarioRaceway::Render(struct UnkStruct_800DC5EC* arg0) {
u16 sp22 = arg0->pathCounter;
u16 temp_t0 = arg0->playerDirection;
@@ -333,19 +357,9 @@ void MarioRaceway::RenderCredits() {
void MarioRaceway::Collision() {}
-void MarioRaceway::GenerateCollision() {
- generate_collision_mesh_with_defaults(segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07001140)));
- if (gScreenModeSelection == SCREEN_MODE_1P) {
- // d_course_mario_raceway_packed_dl_8E8
- generate_collision_mesh_with_defaults(segmented_gfx_to_virtual(reinterpret_cast<void*>(0x070008E8)));
- } else {
- // d_course_mario_raceway_packed_dl_2D68
- generate_collision_mesh_with_defaults(segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07002D68)));
- }
-
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_mario_raceway_addr));
- func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
+void MarioRaceway::CreditsSpawnActors() {
+ dma_textures(gTextureTrees1, 0x35B, 0x800);
+ spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_mario_raceway_tree_spawns));
}
void MarioRaceway::Destroy() { }
diff --git a/src/engine/courses/MarioRaceway.h b/src/engine/courses/MarioRaceway.h
index 6857c19a2..ef0fb904b 100644
--- a/src/engine/courses/MarioRaceway.h
+++ b/src/engine/courses/MarioRaceway.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
@@ -33,11 +35,9 @@ public:
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
+ virtual void CreditsSpawnActors() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/MooMooFarm.cpp b/src/engine/courses/MooMooFarm.cpp
index f755dde39..6517eab82 100644
--- a/src/engine/courses/MooMooFarm.cpp
+++ b/src/engine/courses/MooMooFarm.cpp
@@ -6,7 +6,8 @@
#include "MooMooFarm.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/actors/AFinishline.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/moo_moo_farm_data.h"
extern "C" {
@@ -103,6 +104,14 @@ MooMooFarm::MooMooFarm() {
Props.Skybox.FloorTopLeft = {255, 184, 99};
}
+void MooMooFarm::Load() {
+ Course::Load();
+
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_moo_moo_farm_addr));
+ func_80295C6C();
+ D_8015F8E4 = gCourseMinY - 10.0f;
+}
+
void MooMooFarm::LoadTextures() {
dma_textures(gTextureTrees4Left, 0x000003E8U, 0x00000800U);
dma_textures(gTextureTrees4Right, 0x000003E8U, 0x00000800U);
@@ -119,12 +128,28 @@ void MooMooFarm::LoadTextures() {
}
void MooMooFarm::SpawnActors() {
+ gWorldInstance.AddActor(new AFinishline());
+
if (gPlayerCountSelection1 != 4) {
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_moo_moo_farm_tree_spawn));
}
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_moo_moo_farm_item_box_spawns));
}
+void MooMooFarm::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][140], 140, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][225], 225, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][316], 316, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][434], 434, 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 MooMooFarm::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust0, 0x479, 0xC00));
@@ -237,26 +262,12 @@ void MooMooFarm::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-void MooMooFarm::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(40, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(100, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(265, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(285, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(420, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void MooMooFarm::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void MooMooFarm::SetStaffGhost() {}
-
-void MooMooFarm::BeginPlay() {}
-
void MooMooFarm::Render(struct UnkStruct_800DC5EC* arg0) {
s16 temp_s0 = arg0->pathCounter;
s16 temp_s1 = arg0->playerDirection;
@@ -336,10 +347,20 @@ void MooMooFarm::RenderCredits() {
void MooMooFarm::Collision() {}
-void MooMooFarm::GenerateCollision() {
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_moo_moo_farm_addr));
- func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
+void MooMooFarm::CreditsSpawnActors() {
+ dma_textures(gTextureTrees4Left, 0x3E8, 0x800);
+ dma_textures(gTextureTrees4Right, 0x3E8, 0x800);
+ dma_textures(gTextureCow01Left, 0x400, 0x800);
+ dma_textures(gTextureCow01Right, 0x400, 0x800);
+ dma_textures(gTextureCow02Left, 0x400, 0x800);
+ dma_textures(gTextureCow02Right, 0x400, 0x800);
+ dma_textures(gTextureCow03Left, 0x400, 0x800);
+ dma_textures(gTextureCow03Right, 0x400, 0x800);
+ dma_textures(gTextureCow04Left, 0x400, 0x800);
+ dma_textures(gTextureCow04Right, 0x400, 0x800);
+ dma_textures(gTextureCow05Left, 0x400, 0x800);
+ dma_textures(gTextureCow05Right, 0x400, 0x800);
+ spawn_foliage((struct ActorSpawnData*) LOAD_ASSET_RAW(d_course_moo_moo_farm_tree_spawn));
}
void MooMooFarm::Destroy() { }
diff --git a/src/engine/courses/MooMooFarm.h b/src/engine/courses/MooMooFarm.h
index 71eff8913..fb27ef725 100644
--- a/src/engine/courses/MooMooFarm.h
+++ b/src/engine/courses/MooMooFarm.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
@@ -34,12 +36,9 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
+ virtual void CreditsSpawnActors() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/PodiumCeremony.cpp b/src/engine/courses/PodiumCeremony.cpp
index 08da45829..9488b8b21 100644
--- a/src/engine/courses/PodiumCeremony.cpp
+++ b/src/engine/courses/PodiumCeremony.cpp
@@ -6,8 +6,9 @@
#include "PodiumCeremony.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/royal_raceway_data.h"
+#include "assets/ceremony_data.h"
extern "C" {
#include "main.h"
@@ -29,6 +30,7 @@ extern "C" {
#include "actors.h"
#include "collision.h"
#include "memory.h"
+ #include "courses/staff_ghost_data.h"
extern const char *royal_raceway_dls[];
}
@@ -49,7 +51,7 @@ PodiumCeremony::PodiumCeremony() {
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
- Props.PathSizes = {0x3E8, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0};
+ Props.PathSizes = {500, 500, 500, 500, 1, 0, 0, 0, 0, 0, 0};
Props.D_0D009418[0] = 4.1666665f;
Props.D_0D009418[1] = 5.5833334f;
@@ -71,12 +73,12 @@ PodiumCeremony::PodiumCeremony() {
Props.D_0D009808[2] = 5.75f;
Props.D_0D009808[3] = 6.3333334f;
- Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_royal_raceway_unknown_waypoints);
- Props.PathTable[1] = NULL;
- Props.PathTable[2] = NULL;
- Props.PathTable[3] = NULL;
+ Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(podium_ceremony_path);
+ Props.PathTable[1] = (TrackWaypoint*)LOAD_ASSET_RAW(podium_ceremony_path_2);
+ Props.PathTable[2] = (TrackWaypoint*)LOAD_ASSET_RAW(podium_ceremony_path_3);
+ Props.PathTable[3] = (TrackWaypoint*)LOAD_ASSET_RAW(podium_ceremony_path_4);
- Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_royal_raceway_track_waypoints);
+ Props.PathTable2[0] = NULL;
Props.PathTable2[1] = NULL;
Props.PathTable2[2] = NULL;
Props.PathTable2[3] = NULL;
@@ -96,6 +98,14 @@ PodiumCeremony::PodiumCeremony() {
Props.Skybox.FloorTopLeft = {255, 224, 240};
}
+void PodiumCeremony::Load() {
+ Course::Load();
+
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_royal_raceway_addr));
+ func_80295C6C();
+ D_8015F8E4 = -60.0f;
+}
+
void PodiumCeremony::LoadTextures() {
}
@@ -105,6 +115,18 @@ void PodiumCeremony::SpawnActors() {
spawn_piranha_plants((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_royal_raceway_piranha_plant_spawn));
}
+void PodiumCeremony::SpawnVehicles() {
+ Vec3f pos = {0, 0, 0};
+
+ gWorldInstance.AddBombKart(pos, &D_80164550[3][3], 3, 5, 1.25f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[3][40], 40, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[3][60], 60, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[3][80], 80, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[3][100], 100, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[3][120], 120, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[3][140], 140, 0, 1.0f);
+}
+
// Likely sets minimap boundaries
void PodiumCeremony::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust4, 0x3F8, 0x1000));
@@ -163,36 +185,12 @@ void PodiumCeremony::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-void PodiumCeremony::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(40, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(100, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(265, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(285, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(420, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void PodiumCeremony::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void PodiumCeremony::SetStaffGhost() {
- u32 temp_v0 = func_800B4E24(0) & 0xfffff;
- if (temp_v0 <= 16000) {
- D_80162DD6 = 0;
- D_80162DF4 = 0;
- } else {
- D_80162DD6 = 1;
- D_80162DF4 = 1;
- }
- D_80162DC4 = d_royal_raceway_staff_ghost;
- D_80162DE4 = 6;
-}
-
-void PodiumCeremony::BeginPlay() { }
void PodiumCeremony::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -228,10 +226,4 @@ void PodiumCeremony::RenderCredits() {
void PodiumCeremony::Collision() {}
-void PodiumCeremony::GenerateCollision() {
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_royal_raceway_addr));
- func_80295C6C();
- D_8015F8E4 = -60.0f;
-}
-
void PodiumCeremony::Destroy() { }
diff --git a/src/engine/courses/PodiumCeremony.h b/src/engine/courses/PodiumCeremony.h
index c8f8b7c06..7f9de6b1d 100644
--- a/src/engine/courses/PodiumCeremony.h
+++ b/src/engine/courses/PodiumCeremony.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
@@ -33,12 +35,8 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/RainbowRoad.cpp b/src/engine/courses/RainbowRoad.cpp
index 038a40541..4836611fb 100644
--- a/src/engine/courses/RainbowRoad.cpp
+++ b/src/engine/courses/RainbowRoad.cpp
@@ -6,7 +6,8 @@
#include "RainbowRoad.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/actors/AFinishline.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/rainbow_road_data.h"
extern "C" {
@@ -100,13 +101,48 @@ RainbowRoad::RainbowRoad() {
Props.Skybox.FloorTopLeft = {0, 0, 0};
}
+void RainbowRoad::Load() {
+ Course::Load();
+
+ D_800DC5C8 = 1;
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_rainbow_road_addr));
+ func_80295C6C();
+ D_8015F8E4 = 0.0f;
+ // d_course_rainbow_road_packed_dl_2068
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07002068), -0x6A, 255, 255, 255);
+ // d_course_rainbow_road_packed_dl_1E18
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07001E18), -0x6A, 255, 255, 255);
+ // d_course_rainbow_road_packed_dl_1318
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07001318), 255, 255, 255, 0);
+ if (gGamestate != CREDITS_SEQUENCE) {
+ // d_course_rainbow_road_packed_dl_1FB8
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07001FB8), -0x6A, 255, 255, 255);
+ }
+}
+
void RainbowRoad::LoadTextures() {
}
void RainbowRoad::SpawnActors() {
+ gWorldInstance.AddActor(new AFinishline());
+
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_rainbow_road_item_box_spawns));
}
+void RainbowRoad::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);
+ }
+}
+
void RainbowRoad::InitClouds() {
init_stars(this->Props.Clouds);
}
@@ -157,25 +193,12 @@ void RainbowRoad::WhatDoesThisDo(Player* player, int8_t playerId) {}
void RainbowRoad::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-void RainbowRoad::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(40, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(100, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(265, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(285, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(420, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void RainbowRoad::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void RainbowRoad::SetStaffGhost() {}
-
-void RainbowRoad::BeginPlay() {}
void RainbowRoad::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -190,25 +213,30 @@ void RainbowRoad::RenderCredits() {
void RainbowRoad::Collision() {}
-void RainbowRoad::GenerateCollision() {
- D_800DC5C8 = 1;
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_rainbow_road_addr));
- func_80295C6C();
- D_8015F8E4 = 0.0f;
+void RainbowRoad::Waypoints(Player* player, int8_t playerId) {
+ player->nearestWaypointId = gCopyNearestWaypointByPlayerId[playerId];
+}
+
+void RainbowRoad::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) {
+ Mat4 matrix;
+
+ gDPPipeSync(gDisplayListHead++);
+ mtxf_identity(matrix);
+ render_set_position(matrix, 0);
+ gSPClearGeometryMode(gDisplayListHead++, G_CULL_BACK);
+ render_course_segments(rainbow_road_dls, screen);
+ gSPSetGeometryMode(gDisplayListHead++, G_CULL_BACK);
+ gDPSetAlphaCompare(gDisplayListHead++, G_AC_NONE);
+ gDPPipeSync(gDisplayListHead++);
+}
+
+void RainbowRoad::CreditsSpawnActors() {
// d_course_rainbow_road_packed_dl_2068
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07002068), -0x6A, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07002068), -0x6A, 0xFF, 0xFF, 0xFF);
// d_course_rainbow_road_packed_dl_1E18
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07001E18), -0x6A, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07001E18), -0x6A, 0xFF, 0xFF, 0xFF);
// d_course_rainbow_road_packed_dl_1318
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07001318), 255, 255, 255, 0);
- if (gGamestate != CREDITS_SEQUENCE) {
- // d_course_rainbow_road_packed_dl_1FB8
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07001FB8), -0x6A, 255, 255, 255);
- }
-}
-
-void RainbowRoad::Waypoints(Player* player, int8_t playerId) {
- player->nearestWaypointId = gCopyNearestWaypointByPlayerId[playerId];
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07001318), -1, 0xFF, 0xFF, 0);
}
void RainbowRoad::Destroy() {}
diff --git a/src/engine/courses/RainbowRoad.h b/src/engine/courses/RainbowRoad.h
index 6c32adb51..5f6b0e5e7 100644
--- a/src/engine/courses/RainbowRoad.h
+++ b/src/engine/courses/RainbowRoad.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
virtual void InitClouds() override;
virtual void UpdateClouds(s32, Camera*) override;
virtual void MinimapSettings() override;
@@ -36,13 +38,11 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
+ virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override;
+ virtual void CreditsSpawnActors() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/RoyalRaceway.cpp b/src/engine/courses/RoyalRaceway.cpp
index e252d866f..ded9ec464 100644
--- a/src/engine/courses/RoyalRaceway.cpp
+++ b/src/engine/courses/RoyalRaceway.cpp
@@ -6,7 +6,8 @@
#include "RoyalRaceway.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/actors/AFinishline.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/royal_raceway_data.h"
extern "C" {
@@ -29,6 +30,7 @@ extern "C" {
#include "actors.h"
#include "collision.h"
#include "memory.h"
+ #include "courses/staff_ghost_data.h"
extern const char *royal_raceway_dls[];
}
@@ -100,6 +102,14 @@ RoyalRaceway::RoyalRaceway() {
Props.Skybox.FloorTopLeft = {255, 224, 240};
}
+void RoyalRaceway::Load() {
+ Course::Load();
+
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_royal_raceway_addr));
+ func_80295C6C();
+ D_8015F8E4 = -60.0f;
+}
+
void RoyalRaceway::LoadTextures() {
dma_textures(gTextureTrees3, 0x000003E8U, 0x00000800U);
dma_textures(gTextureTrees7, 0x000003E8U, 0x00000800U);
@@ -115,11 +125,27 @@ void RoyalRaceway::LoadTextures() {
}
void RoyalRaceway::SpawnActors() {
+ gWorldInstance.AddActor(new AFinishline());
+
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_royal_raceway_tree_spawn));
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));
}
+void RoyalRaceway::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, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][296], 296, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][400], 400, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][746], 746, 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 RoyalRaceway::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust4, 0x3F8, 0x1000));
@@ -178,16 +204,6 @@ void RoyalRaceway::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-void RoyalRaceway::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(40, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(100, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(265, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(285, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(420, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void RoyalRaceway::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
@@ -207,7 +223,6 @@ void RoyalRaceway::SetStaffGhost() {
D_80162DE4 = 6;
}
-void RoyalRaceway::BeginPlay() { }
void RoyalRaceway::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
@@ -243,12 +258,6 @@ void RoyalRaceway::RenderCredits() {
void RoyalRaceway::Collision() {}
-void RoyalRaceway::GenerateCollision() {
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_royal_raceway_addr));
- func_80295C6C();
- D_8015F8E4 = -60.0f;
-}
-
void RoyalRaceway::Waypoints(Player* player, int8_t playerId) {
s16 waypoint = gNearestWaypointByPlayerId[playerId];
if ((waypoint >= 0x258) && (waypoint < 0x2A4)) {
@@ -261,4 +270,15 @@ void RoyalRaceway::Waypoints(Player* player, int8_t playerId) {
}
}
+void RoyalRaceway::ScrollingTextures() {
+ D_802B87BC -= 20;
+ if (D_802B87BC < 0) {
+ D_802B87BC = 0xFF;
+ }
+ // d_course_royal_raceway_packed_dl_A6A8
+ find_and_set_tile_size((uintptr_t) segmented_gfx_to_virtual((void*)0x0700A6A8), 0, D_802B87BC);
+ // d_course_royal_raceway_packed_dl_A648
+ find_and_set_tile_size((uintptr_t) segmented_gfx_to_virtual((void*)0x0700A648), 0, D_802B87BC);
+}
+
void RoyalRaceway::Destroy() { }
diff --git a/src/engine/courses/RoyalRaceway.h b/src/engine/courses/RoyalRaceway.h
index 07498c6eb..0a7cd3e6a 100644
--- a/src/engine/courses/RoyalRaceway.h
+++ b/src/engine/courses/RoyalRaceway.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void SomeSounds() override;
@@ -33,12 +35,10 @@ public:
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
+ virtual void ScrollingTextures() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/SherbetLand.cpp b/src/engine/courses/SherbetLand.cpp
index 38439eb95..19bfa573e 100644
--- a/src/engine/courses/SherbetLand.cpp
+++ b/src/engine/courses/SherbetLand.cpp
@@ -6,7 +6,8 @@
#include "SherbetLand.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/actors/AFinishline.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/sherbet_land_data.h"
extern "C" {
@@ -30,6 +31,7 @@ extern "C" {
#include "collision.h"
#include "memory.h"
extern const char *sherbet_land_dls[];
+ extern const char *sherbet_land_dls_2[];
}
SherbetLand::SherbetLand() {
@@ -100,13 +102,41 @@ SherbetLand::SherbetLand() {
Props.Skybox.FloorTopLeft = {216, 232, 248};
}
+void SherbetLand::Load() {
+ Course::Load();
+
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_sherbet_land_addr));
+ func_80295C6C();
+ D_8015F8E4 = -18.0f;
+ // d_course_sherbet_land_packed_dl_1EB8
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07001EB8), -0x4C, 255, 255, 255);
+ // d_course_sherbet_land_packed_dl_2308
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07002308), -0x6A, 255, 255, 255);
+}
+
void SherbetLand::LoadTextures() {
}
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));
@@ -146,25 +176,12 @@ void SherbetLand::WhatDoesThisDo(Player* player, int8_t playerId) {}
void SherbetLand::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-void SherbetLand::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(40, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(100, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(265, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(285, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(420, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void SherbetLand::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void SherbetLand::SetStaffGhost() {}
-
-void SherbetLand::BeginPlay() { }
void SherbetLand::Render(struct UnkStruct_800DC5EC* arg0) {
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -180,14 +197,37 @@ void SherbetLand::RenderCredits() {
void SherbetLand::Collision() {}
-void SherbetLand::GenerateCollision() {
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_sherbet_land_addr));
- func_80295C6C();
- D_8015F8E4 = -18.0f;
+void SherbetLand::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) {
+ Mat4 matrix;
+
+ gDPPipeSync(gDisplayListHead++);
+ gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
+ gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
+ gDPSetBlendMask(gDisplayListHead++, 0xFF);
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
+ gDPSetTextureFilter(gDisplayListHead++, G_TF_BILERP);
+ gDPSetTexturePersp(gDisplayListHead++, G_TP_PERSP);
+
+ mtxf_identity(matrix);
+ render_set_position(matrix, 0);
+ render_course_segments(sherbet_land_dls_2, screen);
+
+ gDPSetAlphaCompare(gDisplayListHead++, G_AC_NONE);
+ if ((func_80290C20(screen->camera) == 1) && (func_802AAB4C(screen->player) < screen->player->pos[1])) {
+ gSPSetGeometryMode(gDisplayListHead++, G_ZBUFFER);
+ gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
+ gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
+ // d_course_sherbet_land_packed_dl_2B48
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07002B48));
+ }
+ gDPPipeSync(gDisplayListHead++);
+}
+
+void SherbetLand::CreditsSpawnActors() {
// d_course_sherbet_land_packed_dl_1EB8
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07001EB8), -0x4C, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07001EB8), -0x4C, 0xFF, 0xFF, 0xFF);
// d_course_sherbet_land_packed_dl_2308
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07002308), -0x6A, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07002308), -0x6A, 0xFF, 0xFF, 0xFF);
}
void SherbetLand::Destroy() { }
diff --git a/src/engine/courses/SherbetLand.h b/src/engine/courses/SherbetLand.h
index 7ab4f9028..177410ca7 100644
--- a/src/engine/courses/SherbetLand.h
+++ b/src/engine/courses/SherbetLand.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
@@ -34,12 +36,10 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
+ virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override;
+ virtual void CreditsSpawnActors() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/Skyscraper.cpp b/src/engine/courses/Skyscraper.cpp
index 82a16ad93..df26ceccb 100644
--- a/src/engine/courses/Skyscraper.cpp
+++ b/src/engine/courses/Skyscraper.cpp
@@ -6,7 +6,7 @@
#include "Skyscraper.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/skyscraper_data.h"
extern "C" {
@@ -101,10 +101,38 @@ Skyscraper::Skyscraper() {
Props.Skybox.FloorTopLeft = {0, 0, 0};
}
+void Skyscraper::Load() {
+ Course::Load();
+
+ // d_course_skyscraper_packed_dl_1110
+ generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07001110), 1);
+ // d_course_skyscraper_packed_dl_258
+ generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000258), 1);
+ func_80295C6C();
+
+ D_8015F8E4 = -480.0f;
+}
+
void Skyscraper::LoadTextures() {
}
-void Skyscraper::SpawnActors() {}
+void Skyscraper::SpawnActors() {
+ spawn_all_item_boxes((ActorSpawnData*)LOAD_ASSET_RAW(d_course_skyscraper_item_box_spawns));
+}
+
+void Skyscraper::SpawnVehicles() {
+ if (gModeSelection == VERSUS) {
+ Vec3f pos = {0, 0, 0};
+
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][20], 20, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][40], 40, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][60], 60, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][80], 80, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][100], 100, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][120], 120, 0, 1.0f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][140], 140, 0, 1.0f);
+ }
+}
// Likely sets minimap boundaries
void Skyscraper::MinimapSettings() {
@@ -121,17 +149,12 @@ void Skyscraper::WhatDoesThisDo(Player* player, int8_t playerId) {}
void Skyscraper::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-void Skyscraper::SpawnBombKarts() {}
-
// Positions the finishline on the minimap
void Skyscraper::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void Skyscraper::SetStaffGhost() {}
-
-void Skyscraper::BeginPlay() { }
void Skyscraper::Render(struct UnkStruct_800DC5EC* arg0) {
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
@@ -159,16 +182,6 @@ void Skyscraper::RenderCredits() {}
void Skyscraper::Collision() {}
-void Skyscraper::GenerateCollision() {
- // d_course_skyscraper_packed_dl_1110
- generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07001110), 1);
- // d_course_skyscraper_packed_dl_258
- generate_collision_mesh_with_default_section_id((Gfx*) segmented_gfx_to_virtual((void*)0x07000258), 1);
- func_80295C6C();
-
- D_8015F8E4 = -480.0f;
-}
-
void Skyscraper::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = 0;
}
diff --git a/src/engine/courses/Skyscraper.h b/src/engine/courses/Skyscraper.h
index a37c6e6ff..6658b43e6 100644
--- a/src/engine/courses/Skyscraper.h
+++ b/src/engine/courses/Skyscraper.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
//virtual void InitClouds() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
@@ -33,13 +35,9 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/TestCourse.cpp b/src/engine/courses/TestCourse.cpp
index dcc64ec79..b3383a3b0 100644
--- a/src/engine/courses/TestCourse.cpp
+++ b/src/engine/courses/TestCourse.cpp
@@ -6,7 +6,14 @@
#include "TestCourse.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/actors/AFinishline.h"
+#include "engine/vehicles/OBombKart.h"
+#include "assets/mario_raceway_data.h"
+#include "assets/bowsers_castle_data.h"
+#include "assets/bowsers_castle_displaylists.h"
+#include "engine/actors/ATree.h"
+
+#include "engine/actors/ACloud.h"
extern "C" {
#include "main.h"
@@ -29,10 +36,10 @@ extern "C" {
#include "collision.h"
#include "memory.h"
typedef struct {
- Gfx* addr;
- u8 surfaceType;
- u8 sectionId;
- u16 flags;
+ Gfx* addr;
+ u8 surfaceType;
+ u8 sectionId;
+ u16 flags;
} TrackSections;
extern Gfx test_course_dls[];
extern Vtx mario_Plane_001_mesh_vtx_1[];
@@ -108,8 +115,13 @@ TestCourse::TestCourse() {
}
void TestCourse::Load() {
- gSegmentTable[4] = reinterpret_cast<uintptr_t>(&mario_Plane_001_mesh_vtx_1[0]);
- //gSegmentTable[7] = reinterpret_cast<uintptr_t>(&gfx[0]);
+ Course::Load(mario_Plane_001_mesh_vtx_1, NULL);
+
+ generate_collision_mesh_with_defaults(mario_Plane_001_mesh);
+
+ parse_course_displaylists((TrackSectionsI*)test_course_addr);
+ func_80295C6C();
+ D_8015F8E4 = gCourseMinY - 10.0f;
}
void TestCourse::LoadTextures() {
@@ -126,30 +138,39 @@ void TestCourse::LoadTextures() {
}
void TestCourse::SpawnActors() {
-struct ActorSpawnData itemboxes[] = {
- { 200, 1500, 200 , 0},
- { 350, 2500, 300 , 1},
- { 400, 2000, 350 , 2},
- { 40, 0, -800, 0},
- { -40, 0, -800, 0},
- { 0, 0, -800, 0},
- { 999, 6, 482, 0},
- { 1064, 8, 275, {0}},
- { 1028, 5, -39 , {0}},
- { 320, 0, 1020, {0}},
- { 293, 0, 950, {0}},
- {{ -32768, 0, 0 }, {0}},
-};
+ struct ActorSpawnData itemboxes[] = {
+ { 200, 1500, 200 , 0},
+ { 350, 2500, 300 , 1},
+ { 400, 2000, 350 , 2},
+ { 40, 0, -800, 0},
+ { -40, 0, -800, 0},
+ { 0, 0, -800, 0},
+ { 999, 6, 482, 0},
+ { 1064, 8, 275, {0}},
+ { 1028, 5, -39 , {0}},
+ { 320, 0, 1020, {0}},
+ { 293, 0, 950, {0}},
+ {{ -32768, 0, 0 }, {0}},
+ };
+
+ struct ActorSpawnData rocks[] = {
+ {{ 200, 1500, 200 }, {0}},
+ {{ 350, 2500, 300 }, {1}},
+ {{ 400, 2000, 350 }, {2}},
+ {{ -32768, 0, 0 }, {0}},
+ };
+
+ gWorldInstance.AddActor(new AFinishline());
-struct ActorSpawnData rocks[] = {
- {{ 200, 1500, 200 }, {0}},
- {{ 350, 2500, 300 }, {1}},
- {{ 400, 2000, 350 }, {2}},
- {{ -32768, 0, 0 }, {0}},
-};
spawn_all_item_boxes(itemboxes);
spawn_falling_rocks(rocks);
+ Vec3f test = {-100, 0, -150};
+ Vec3s rot = {0, 0, 0};
+ Vec3f vel = {0, 0, 0};
+
+ add_actor_to_empty_slot(test, rot, vel, ACTOR_TREE_MARIO_RACEWAY);
+
struct RailroadCrossing* rrxing;
Vec3f position;
Vec3f velocity = { 0.0f, 0.0f, 0.0f };
@@ -160,9 +181,12 @@ struct ActorSpawnData rocks[] = {
uintptr_t* crossing1 = (uintptr_t*) gWorldInstance.AddCrossing(crossingPos, 0, 2, 900.0f, 650.0f);
position[0] *= gCourseDirection;
- rrxing = (struct RailroadCrossing*) &gActorList[add_actor_to_empty_slot(position, rotation, velocity,
- ACTOR_RAILROAD_CROSSING)];
+ rrxing = (struct RailroadCrossing*) GET_ACTOR(add_actor_to_empty_slot(position, rotation, velocity,
+ ACTOR_RAILROAD_CROSSING));
rrxing->crossingTrigger = crossing1;
+
+ Vec3f pos = {-80, 7, -20};
+ gWorldInstance.AddActor(new ACloud(pos));
}
// Likely sets minimap boundaries
@@ -241,8 +265,14 @@ void TestCourse::SpawnVehicles() {
gVehicle2DWaypointLength = 53;
D_80162EB0 = spawn_actor_on_surface(test_course_path2D[0].x, 2000.0f, test_course_path2D[0].z);
- gWorldInstance.AddTrain(5, 5.0f, 0);
- gWorldInstance.AddTrain(5, 5.0f, 8);
+ gWorldInstance.AddTrain(5, 2.5f, 0);
+ gWorldInstance.AddTrain(5, 2.5f, 8);
+
+ Vec3f pos = {0, 0, 0};
+
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][25], 25, 2, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][45], 45, 3, 0.8333333f);
+
}
void TestCourse::UpdateVehicles() {
@@ -283,25 +313,12 @@ void TestCourse::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-void TestCourse::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(40, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(100, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(265, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(285, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(420, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void TestCourse::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void TestCourse::SetStaffGhost() {}
-
-void TestCourse::BeginPlay() { }
void TestCourse::Render(struct UnkStruct_800DC5EC* arg0) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@@ -322,12 +339,4 @@ void TestCourse::RenderCredits() {
void TestCourse::Collision() {}
-void TestCourse::GenerateCollision() {
- generate_collision_mesh_with_defaults(mario_Plane_001_mesh);
-
- parse_course_displaylists((TrackSectionsI*)test_course_addr);
- func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
-}
-
void TestCourse::Destroy() { }
diff --git a/src/engine/courses/TestCourse.h b/src/engine/courses/TestCourse.h
index 9d988e4c6..4f0e83b9c 100644
--- a/src/engine/courses/TestCourse.h
+++ b/src/engine/courses/TestCourse.h
@@ -33,14 +33,10 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void SpawnVehicles() override;
virtual void UpdateVehicles() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/ToadsTurnpike.cpp b/src/engine/courses/ToadsTurnpike.cpp
index d66faf571..e629b76ef 100644
--- a/src/engine/courses/ToadsTurnpike.cpp
+++ b/src/engine/courses/ToadsTurnpike.cpp
@@ -6,8 +6,9 @@
#include "ToadsTurnpike.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/toads_turnpike_data.h"
+#include "engine/actors/AFinishline.h"
#include "engine/vehicles/Utils.h"
@@ -105,10 +106,30 @@ ToadsTurnpike::ToadsTurnpike() {
Props.Skybox.FloorTopLeft = {209, 65, 23};
}
+void ToadsTurnpike::Load() {
+ Course::Load();
+
+ D_801625EC = 43;
+ D_801625F4 = 13;
+ D_801625F0 = 4;
+ D_802B87B0 = 993;
+ D_802B87B4 = 1000;
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_toads_turnpike_addr));
+ func_80295C6C();
+ D_8015F8E4 = gCourseMinY - 10.0f;
+}
+
void ToadsTurnpike::LoadTextures() {
}
void ToadsTurnpike::SpawnActors() {
+ Vec3f pos;
+ pos[0] = (gIsMirrorMode != 0) ? D_80164490->posX + 138.0f : D_80164490->posX - 138.0f;
+ pos[1] = (f32) (D_80164490->posY - 15);
+ pos[2] = D_80164490->posZ;
+
+ gWorldInstance.AddActor(new AFinishline(pos));
+
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_toads_turnpike_item_box_spawns));
}
@@ -158,26 +179,12 @@ void ToadsTurnpike::WhatDoesThisDoAI(Player* player, int8_t playerId) {
}
}
-void ToadsTurnpike::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(40, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(100, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(265, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(285, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(420, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void ToadsTurnpike::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void ToadsTurnpike::SetStaffGhost() {}
-
-void ToadsTurnpike::BeginPlay() {}
-
void ToadsTurnpike::Render(struct UnkStruct_800DC5EC* arg0) {
func_802B5D64(D_800DC610, D_802B87D4, 0, 1);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
@@ -213,6 +220,8 @@ void ToadsTurnpike::Collision() {}
void ToadsTurnpike::SpawnVehicles() {
f32 a = ((gCCSelection * 90.0) / 216.0f) + 4.583333333333333;
f32 b = ((gCCSelection * 90.0) / 216.0f) + 2.9166666666666665;
+ a /= 2; // Normally vehicle logic is only ran every 2 frames. This slows the vehicles down to match.
+ b /= 2;
uint32_t waypoint;
if (gModeSelection == TIME_TRIALS) {
@@ -256,17 +265,18 @@ void ToadsTurnpike::SpawnVehicles() {
gWorldInstance.AddCar(a, b, &D_80164550[0][0], waypoint);
}
}
-}
-void ToadsTurnpike::GenerateCollision() {
- D_801625EC = 43;
- D_801625F4 = 13;
- D_801625F0 = 4;
- D_802B87B0 = 993;
- D_802B87B4 = 1000;
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_toads_turnpike_addr));
- func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
+ 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);
+ }
}
void ToadsTurnpike::Destroy() { }
diff --git a/src/engine/courses/ToadsTurnpike.h b/src/engine/courses/ToadsTurnpike.h
index 8bba69de5..7a097cce3 100644
--- a/src/engine/courses/ToadsTurnpike.h
+++ b/src/engine/courses/ToadsTurnpike.h
@@ -24,6 +24,7 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
virtual void InitClouds() override;
@@ -33,13 +34,9 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void SpawnVehicles() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/WarioStadium.cpp b/src/engine/courses/WarioStadium.cpp
index bc90d15b6..39447b590 100644
--- a/src/engine/courses/WarioStadium.cpp
+++ b/src/engine/courses/WarioStadium.cpp
@@ -6,9 +6,10 @@
#include "WarioStadium.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/wario_stadium_data.h"
#include "engine/actors/AWarioSign.h"
+#include "engine/actors/AFinishline.h"
extern "C" {
#include "main.h"
@@ -103,23 +104,68 @@ WarioStadium::WarioStadium() {
Props.Skybox.FloorTopLeft = {0, 0, 0};
}
+void WarioStadium::Load() {
+ Course::Load();
+
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_wario_stadium_addr));
+ func_80295C6C();
+ D_8015F8E4 = gCourseMinY - 10.0f;
+ // d_course_wario_stadium_packed_dl_C50
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000C50), 100, 255, 255, 255);
+ // d_course_wario_stadium_packed_dl_BD8
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000BD8), 100, 255, 255, 255);
+ // d_course_wario_stadium_packed_dl_B60
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000B60), 100, 255, 255, 255);
+ // d_course_wario_stadium_packed_dl_AE8
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000AE8), 100, 255, 255, 255);
+ // d_course_wario_stadium_packed_dl_CC8
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000CC8), 100, 255, 255, 255);
+ // d_course_wario_stadium_packed_dl_D50
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000D50), 100, 255, 255, 255);
+ // d_course_wario_stadium_packed_dl_DD0
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000DD0), 100, 255, 255, 255);
+ // d_course_wario_stadium_packed_dl_E48
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000E48), 100, 255, 255, 255);
+}
+
void WarioStadium::LoadTextures() {
}
void WarioStadium::SpawnActors() {
+ Vec3f finish;
+ finish[0] = (gIsMirrorMode != 0) ? D_80164490->posX + 12.0f : D_80164490->posX - 12.0f;(gIsMirrorMode != 0) ? D_80164490->posX + 12.0f : D_80164490->posX - 12.0f;
+ finish[1] = D_8015F8D0[1] = (f32) (D_80164490->posY - 15);
+ finish[2] = D_8015F8D0[2] = D_80164490->posZ;
+
+ gWorldInstance.AddActor(new AFinishline(finish));
+
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_wario_stadium_item_box_spawns));
Vec3f pos = {-131.0f, 83.0f, 286.0f};
pos[0] *= gCourseDirection;
- gWorldInstance.AddActor(std::make_unique<AWarioSign>(pos));
+ gWorldInstance.AddActor(new AWarioSign(pos));
Vec3f pos2 = {-2353.0f, 72.0f, -1608.0f};
pos2[0] *= gCourseDirection;
- gWorldInstance.AddActor(std::make_unique<AWarioSign>(pos2));
+ gWorldInstance.AddActor(new AWarioSign(pos2));
Vec3f pos3 = {-2622.0f, 79.0f, 739.0f};
pos3[0] *= gCourseDirection;
- gWorldInstance.AddActor(std::make_unique<AWarioSign>(pos3));
+ gWorldInstance.AddActor(new AWarioSign(pos3));
+}
+
+void WarioStadium::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);
+ }
}
void WarioStadium::InitClouds() {
@@ -155,25 +201,12 @@ void WarioStadium::WhatDoesThisDo(Player* player, int8_t playerId) {}
void WarioStadium::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-void WarioStadium::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(40, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(100, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(265, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(285, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(420, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void WarioStadium::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void WarioStadium::SetStaffGhost() {}
-
-void WarioStadium::BeginPlay() { }
void WarioStadium::Render(struct UnkStruct_800DC5EC* arg0) {
s16 prevFrame;
@@ -272,26 +305,60 @@ void WarioStadium::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Ve
func_8003EE2C(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
}
-void WarioStadium::GenerateCollision() {
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_wario_stadium_addr));
- func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
+void WarioStadium::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) {
+ Mat4 matrix;
+
+ gDPPipeSync(gDisplayListHead++);
+ gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
+ gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
+ gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_XLU_INTER, G_RM_NOOP2);
+ gDPSetBlendMask(gDisplayListHead++, 0xFF);
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
+ gDPSetTextureFilter(gDisplayListHead++, G_TF_BILERP);
+ gDPSetTexturePersp(gDisplayListHead++, G_TP_PERSP);
+
+ mtxf_identity(matrix);
+ render_set_position(matrix, 0);
+
+ gSPClearGeometryMode(gDisplayListHead++, G_CULL_BACK);
+ gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
+ gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_XLU_SURF, G_RM_AA_ZB_XLU_SURF2);
+ gDPSetPrimColor(gDisplayListHead++, 0, 0, 0xFF, 0xFF, 0x00, 0xFF);
+ // d_course_wario_stadium_packed_dl_EC0
+ gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07000EC0));
+ gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 1, 1, G_OFF);
+ gSPSetGeometryMode(gDisplayListHead++, G_CULL_BACK);
+ gDPSetAlphaCompare(gDisplayListHead++, G_AC_NONE);
+ gDPPipeSync(gDisplayListHead++);
+}
+
+void WarioStadium::CreditsSpawnActors() {
+ Vec3f position;
+ Vec3f velocity = { 0, 0, 0 };
+ Vec3s rotation = { 0, 0, 0 };
+
+ vec3f_set(position, -131.0f, 83.0f, 286.0f);
+ add_actor_to_empty_slot(position, rotation, velocity, ACTOR_WARIO_SIGN);
+ vec3f_set(position, -2353.0f, 72.0f, -1608.0f);
+ add_actor_to_empty_slot(position, rotation, velocity, ACTOR_WARIO_SIGN);
+ vec3f_set(position, -2622.0f, 79.0f, 739.0f);
+ add_actor_to_empty_slot(position, rotation, velocity, ACTOR_WARIO_SIGN);
// d_course_wario_stadium_packed_dl_C50
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000C50), 100, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000C50), 0x64, 0xFF, 0xFF, 0xFF);
// d_course_wario_stadium_packed_dl_BD8
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000BD8), 100, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000BD8), 0x64, 0xFF, 0xFF, 0xFF);
// d_course_wario_stadium_packed_dl_B60
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000B60), 100, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000B60), 0x64, 0xFF, 0xFF, 0xFF);
// d_course_wario_stadium_packed_dl_AE8
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000AE8), 100, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000AE8), 0x64, 0xFF, 0xFF, 0xFF);
// d_course_wario_stadium_packed_dl_CC8
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000CC8), 100, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000CC8), 0x64, 0xFF, 0xFF, 0xFF);
// d_course_wario_stadium_packed_dl_D50
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000D50), 100, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000D50), 0x64, 0xFF, 0xFF, 0xFF);
// d_course_wario_stadium_packed_dl_DD0
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000DD0), 100, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000DD0), 0x64, 0xFF, 0xFF, 0xFF);
// d_course_wario_stadium_packed_dl_E48
- find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000E48), 100, 255, 255, 255);
+ find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000E48), 0x64, 0xFF, 0xFF, 0xFF);
}
void WarioStadium::Destroy() { }
diff --git a/src/engine/courses/WarioStadium.h b/src/engine/courses/WarioStadium.h
index f41535be1..14707876e 100644
--- a/src/engine/courses/WarioStadium.h
+++ b/src/engine/courses/WarioStadium.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
virtual void InitClouds() override;
virtual void UpdateClouds(s32,Camera*) override;
virtual void MinimapSettings() override;
@@ -34,13 +36,11 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
+ virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override;
+ virtual void CreditsSpawnActors() override;
virtual void Destroy() override;
};
diff --git a/src/engine/courses/YoshiValley.cpp b/src/engine/courses/YoshiValley.cpp
index fe7672d7e..3c0a195f4 100644
--- a/src/engine/courses/YoshiValley.cpp
+++ b/src/engine/courses/YoshiValley.cpp
@@ -6,7 +6,8 @@
#include "YoshiValley.h"
#include "GameObject.h"
#include "World.h"
-#include "BombKart.h"
+#include "engine/actors/AFinishline.h"
+#include "engine/vehicles/OBombKart.h"
#include "assets/yoshi_valley_data.h"
#include "assets/boo_frames.h"
@@ -101,6 +102,16 @@ YoshiValley::YoshiValley() {
Props.Skybox.FloorTopLeft = {95, 40, 15};
}
+void YoshiValley::Load() {
+ Course::Load();
+
+ Lights1 lights4 = gdSPDefLights1(100, 100, 100, 255, 254, 254, 0, 0, 120);
+ func_802B5D64(&lights4, -0x38F0, 0x1C70, 1);
+ parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_yoshi_valley_addr));
+ func_80295C6C();
+ D_8015F8E4 = gCourseMinY - 10.0f;
+}
+
void YoshiValley::LoadTextures() {
dma_textures(gTextureTrees2, 0x000003E8U, 0x00000800U);
}
@@ -110,6 +121,8 @@ void YoshiValley::SpawnActors() {
Vec3f velocity = { 0.0f, 0.0f, 0.0f };
Vec3s rotation = { 0, 0, 0 };
+ gWorldInstance.AddActor(new AFinishline());
+
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_yoshi_valley_tree_spawn));
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_yoshi_valley_item_box_spawns));
vec3f_set(position, -2300.0f, 0.0f, 634.0f);
@@ -147,6 +160,30 @@ void YoshiValley::InitCourseObjects() {
}
}
+void YoshiValley::SpawnVehicles() {
+ if (gModeSelection == VERSUS) {
+
+ // Note that the waypoint values might be unused for Yoshi's Valley. Entered them because
+ // the original data has values here.
+
+ // Note that the Y height is calculated automatically to place the kart on the surface
+ Vec3f pos = {-1533, 0, -682};
+ gWorldInstance.AddBombKart(pos, NULL, 0, 0, 0.8333333f);
+ Vec3f pos2 = {-1565, 0, -619};
+ gWorldInstance.AddBombKart(pos2, NULL, 10, 0, 0.8333333f);
+ Vec3f pos3 = {-1529, 0, -579};
+ gWorldInstance.AddBombKart(pos3, NULL, 20, 0, 0.8333333f);
+ Vec3f pos4 = {-1588, 0, -534};
+ gWorldInstance.AddBombKart(pos4, NULL, 30, 0, 0.8333333f);
+ Vec3f pos5 = {-1598, 0, -207};
+ gWorldInstance.AddBombKart(pos5, NULL, 40, 0, 0.8333333f);
+ Vec3f pos6 = {-1646, 0, -147};
+ gWorldInstance.AddBombKart(pos6, NULL, 50, 0, 0.8333333f);
+ Vec3f pos7 = {-2532, 0, -445};
+ gWorldInstance.AddBombKart(pos7, NULL, 60, 0, 0.8333333f);
+ }
+}
+
void YoshiValley::UpdateCourseObjects() {
func_80083080();
if (gGamestate != CREDITS_SEQUENCE) {
@@ -168,27 +205,12 @@ void YoshiValley::WhatDoesThisDo(Player* player, int8_t playerId) {}
void YoshiValley::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
-void YoshiValley::SpawnBombKarts() {
- gWorldInstance.AddObject(std::make_unique<OBombKart>(140, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(165, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(330, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(550, 1, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(595, 3, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
- gWorldInstance.AddObject(std::make_unique<OBombKart>(0, 0, 0.8333333, 0, 0, 0, 0));
-}
-
// Positions the finishline on the minimap
void YoshiValley::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
-void YoshiValley::SetStaffGhost() {
-}
-
-void YoshiValley::BeginPlay() { }
-
void YoshiValley::Render(struct UnkStruct_800DC5EC* arg0) {
gDPPipeSync(gDisplayListHead++);
gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEI, G_CC_MODULATEI);
@@ -204,18 +226,20 @@ void YoshiValley::RenderCredits() {
void YoshiValley::Collision() {}
-void YoshiValley::GenerateCollision() {
- Lights1 lights4 = gdSPDefLights1(100, 100, 100, 255, 254, 254, 0, 0, 120);
- func_802B5D64(&lights4, -0x38F0, 0x1C70, 1);
- parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_yoshi_valley_addr));
- func_80295C6C();
- D_8015F8E4 = gCourseMinY - 10.0f;
-}
-
void YoshiValley::Waypoints(Player* player, int8_t playerId) {
player->nearestWaypointId = gCopyNearestWaypointByPlayerId[playerId];
}
-void YoshiValley::Water() {}
+void YoshiValley::ScrollingTextures() {}
+
+void YoshiValley::CreditsSpawnActors() {
+ Vec3f position;
+ Vec3f velocity = { 0, 0, 0 };
+ Vec3s rotation = { 0, 0, 0 };
+
+ vec3f_set(position, -2300.0f, 0.0f, 634.0f);
+ position[0] *= gCourseDirection;
+ add_actor_to_empty_slot(position, rotation, velocity, ACTOR_YOSHI_EGG);
+}
void YoshiValley::Destroy() {}
diff --git a/src/engine/courses/YoshiValley.h b/src/engine/courses/YoshiValley.h
index 8fe294019..d0de64752 100644
--- a/src/engine/courses/YoshiValley.h
+++ b/src/engine/courses/YoshiValley.h
@@ -24,8 +24,10 @@ public:
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
+ virtual void Load() override;
virtual void LoadTextures() override;
virtual void SpawnActors() override;
+ virtual void SpawnVehicles() override;
virtual void MinimapSettings() override;
virtual void InitCourseObjects() override;
virtual void UpdateCourseObjects() override;
@@ -34,14 +36,11 @@ public:
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
virtual void MinimapFinishlinePosition() override;
- virtual void SetStaffGhost() override;
- virtual void BeginPlay() override;
virtual void Render(struct UnkStruct_800DC5EC*) override;
virtual void RenderCredits() override;
virtual void Collision() override;
- virtual void SpawnBombKarts() override;
- virtual void GenerateCollision() override;
- virtual void Water() override;
+ virtual void ScrollingTextures() override;
virtual void Waypoints(Player* player, int8_t playerId) override;
+ virtual void CreditsSpawnActors() override;
virtual void Destroy() override;
};
diff --git a/src/engine/readme.txt b/src/engine/readme.txt
new file mode 100644
index 000000000..da0de518b
--- /dev/null
+++ b/src/engine/readme.txt
@@ -0,0 +1,3 @@
+# Engine
+
+The replacement C++ engine which contains many code refactors for flexibility. \ No newline at end of file
diff --git a/src/engine/vehicles/Boat.cpp b/src/engine/vehicles/Boat.cpp
index bb2cda81d..1e7109e1d 100644
--- a/src/engine/vehicles/Boat.cpp
+++ b/src/engine/vehicles/Boat.cpp
@@ -143,7 +143,7 @@ void ABoat::Tick() {
Velocity[0] = Position[0] - temp_f26;
Velocity[1] = Position[1] - temp_f28;
Velocity[2] = Position[2] - temp_f30;
- paddleBoatActor = &gActorList[ActorIndex];
+ paddleBoatActor = GET_ACTOR(ActorIndex);
paddleBoatActor->pos[0] = Position[0];
paddleBoatActor->pos[1] = Position[1];
paddleBoatActor->pos[2] = Position[2];
diff --git a/src/engine/vehicles/Bus.cpp b/src/engine/vehicles/Bus.cpp
index 2427cf77f..36bb576c6 100644
--- a/src/engine/vehicles/Bus.cpp
+++ b/src/engine/vehicles/Bus.cpp
@@ -133,7 +133,7 @@ void ABus::Tick() {
Velocity[0] = Position[0] - sp5C;
Velocity[1] = Position[1] - sp58;
Velocity[2] = Position[2] - sp54;
- struct Actor* vehicleActor = &gActorList[ActorIndex];
+ struct Actor* vehicleActor = GET_ACTOR(ActorIndex);
vehicleActor->pos[0] = Position[0];
vehicleActor->pos[1] = Position[1];
vehicleActor->pos[2] = Position[2];
diff --git a/src/engine/vehicles/Car.cpp b/src/engine/vehicles/Car.cpp
index f742aaa75..604fe5f2f 100644
--- a/src/engine/vehicles/Car.cpp
+++ b/src/engine/vehicles/Car.cpp
@@ -115,7 +115,7 @@ void ACar::Tick() {
Velocity[0] = Position[0] - sp5C;
Velocity[1] = Position[1] - sp58;
Velocity[2] = Position[2] - sp54;
- struct Actor* vehicleActor = &gActorList[ActorIndex];
+ struct Actor* vehicleActor = GET_ACTOR(ActorIndex);
vehicleActor->pos[0] = Position[0];
vehicleActor->pos[1] = Position[1];
vehicleActor->pos[2] = Position[2];
diff --git a/src/engine/vehicles/OBombKart.cpp b/src/engine/vehicles/OBombKart.cpp
new file mode 100644
index 000000000..907be2119
--- /dev/null
+++ b/src/engine/vehicles/OBombKart.cpp
@@ -0,0 +1,449 @@
+#include <libultraship.h>
+#include "engine/vehicles/OBombKart.h"
+#include <vector>
+
+#include "port/Game.h"
+#include "engine/Matrix.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"
+extern s8 gPlayerCount;
+}
+
+OBombKart::OBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C) {
+
+ Vec3f _pos = {0, 0, 0};
+
+ if (waypoint) { // Spawn kart on waypoint
+ _pos[0] = waypoint->posX;
+ _pos[1] = waypoint->posY;
+ _pos[2] = waypoint->posZ;
+ } else { // Spawn kart on a surface with the provided position
+
+ // Set height to the default value of 2000.0f unless Pos[1] is higher.
+ // This allows placing these on very high surfaces.
+ f32 height = (pos[1] > 2000.0f) ? pos[1] : 2000.0f;
+ _pos[0] = pos[0];
+ _pos[1] = spawn_actor_on_surface(pos[0], height, pos[2]);
+ _pos[2] = pos[2];
+ }
+
+ WaypointIndex = waypointIndex;
+ Unk_3C = unk_3C;
+ State = static_cast<States>(state);
+
+ Pos[0] = _pos[0];
+ Pos[1] = _pos[1];
+ Pos[2] = _pos[2];
+ CenterY = _pos[1];
+ WheelPos[0][0] = _pos[0];
+ WheelPos[0][1] = _pos[1];
+ WheelPos[0][2] = _pos[2];
+ WheelPos[1][0] = _pos[0];
+ WheelPos[1][1] = _pos[1];
+ WheelPos[1][2] = _pos[2];
+ WheelPos[2][0] = _pos[0];
+ WheelPos[2][1] = _pos[1];
+ WheelPos[2][2] = _pos[2];
+ WheelPos[3][0] = _pos[0];
+ WheelPos[3][1] = _pos[1];
+ WheelPos[3][2] = _pos[2];
+ check_bounding_collision(&_Collision, 2.0f, _pos[0], _pos[1], _pos[2]);
+}
+
+void OBombKart::Spawn() {
+ find_unused_obj_index(&ObjectIndex);
+}
+
+void OBombKart::BeginPlay() {
+
+}
+
+void OBombKart::Tick() {
+ f32 sp118;
+ f32 var_f18;
+ TrackWaypoint* temp_v0_2;
+ f32 temp_f0_3;
+ f32 sp108;
+ f32 temp_f14;
+ f32 temp_f16;
+ f32 temp_f0;
+ f32 temp_f0_4;
+ u16 waypoint;
+ f32 unk_3C;
+ u16 someRot;
+ f32 temp_f12;
+ f32 temp_f12_3;
+ f32 temp_f12_4;
+ f32 temp_f14_2;
+ f32 spAC;
+ f32 temp_f16_2;
+ f32 spA0;
+ f32 temp_f2;
+ f32 temp_f2_4;
+ f32 sp94;
+ f32 var_f20;
+ f32 sp88;
+ f32 var_f22;
+ f32 var_f24;
+ States state;
+ u16 bounceTimer;
+ UNUSED u16 sp4C;
+ u16 temp_t6;
+ u16 temp_t7;
+ u16 circleTimer;
+ TrackWaypoint* temp_v0_4;
+ Player* player;
+
+ state = State;
+
+ if (state == States::DISABLED) {
+ return;
+ }
+
+ if (((Unk_4A != 1) || (GetCourse() == GetPodiumCeremony()))) {
+ var_f22 = Pos[0];
+ var_f20 = Pos[1];
+ var_f24 = Pos[2];
+ waypoint = WaypointIndex;
+ unk_3C = Unk_3C;
+ someRot = SomeRot;
+ bounceTimer = BounceTimer;
+ circleTimer = CircleTimer;
+ if ((state != States::DISABLED) && (state != States::EXPLODE)) {
+ if (GetCourse() == GetPodiumCeremony()) {
+ if (D_8016347E == 1) {
+ player = gPlayerFour;
+ temp_f0 = var_f22 - player->pos[0];
+ temp_f2 = var_f20 - player->pos[1];
+ temp_f12 = var_f24 - player->pos[2];
+ if ((((temp_f0 * temp_f0) + (temp_f2 * temp_f2)) + (temp_f12 * temp_f12)) < 25.0f) {
+ circleTimer = 0;
+ state = States::EXPLODE;
+ player->soundEffects |= 0x400000;
+ player->type &= ~0x2000;
+ }
+ }
+ } else {
+
+ for (size_t i = 0; i < gPlayerCount; i++) {
+ player = &gPlayers[i];
+ if (!(player->effects & 0x80000000)) {
+ temp_f0 = var_f22 - player->pos[0];
+ temp_f2 = var_f20 - player->pos[1];
+ temp_f12 = var_f24 - player->pos[2];
+ if ((((temp_f0 * temp_f0) + (temp_f2 * temp_f2)) + (temp_f12 * temp_f12)) < 25.0f) {
+ state = States::EXPLODE;
+ circleTimer = 0;
+ if (GetCourse() == GetFrappeSnowland()) {
+ player->soundEffects |= 0x01000000;
+ } else {
+ player->soundEffects |= 0x400000;
+ }
+ }
+ }
+ }
+ }
+ }
+ switch(state) {
+ case States::CCW:
+ circleTimer = (circleTimer + 356) % 360;
+ temp_t6 = (circleTimer * 0xFFFF) / 360;
+ sp118 = coss(temp_t6) * 25.0;
+ temp_f0_3 = sins(temp_t6) * 25.0;
+ temp_v0_2 = &D_80164550[0][waypoint];
+ var_f22 = temp_v0_2->posX + sp118;
+ var_f20 = CenterY + 3.5f;
+ var_f24 = temp_v0_2->posZ + temp_f0_3;
+ D_80162FB0[0] = var_f22;
+ D_80162FB0[1] = var_f20;
+ D_80162FB0[2] = var_f24;
+ temp_t7 = (((circleTimer + 1) % 360) * 0xFFFF) / 360;
+ sp118 = coss(temp_t7) * 25.0;
+ temp_f0_3 = sins(temp_t7) * 25.0;
+ D_80162FC0[0] = temp_v0_2->posX + sp118;
+ D_80162FC0[1] = temp_v0_2->posY;
+ D_80162FC0[2] = temp_v0_2->posZ + temp_f0_3;
+ someRot = (get_angle_between_two_vectors(D_80162FB0, D_80162FC0) * 0xFFFF) / 65520;
+ break;
+ case States::CW:
+ circleTimer = (circleTimer + 4) % 360;
+ temp_t6 = (circleTimer * 0xFFFF) / 360;
+ sp118 = coss(temp_t6) * 25.0;
+ temp_f0_3 = sins(temp_t6) * 25.0;
+ temp_v0_2 = &D_80164550[0][waypoint];
+ var_f22 = temp_v0_2->posX + sp118;
+ var_f20 = CenterY + 3.5f;
+ var_f24 = temp_v0_2->posZ + temp_f0_3;
+ D_80162FB0[0] = var_f22;
+ D_80162FB0[1] = var_f20;
+ D_80162FB0[2] = var_f24;
+ temp_t7 = (((circleTimer + 1) % 360) * 0xFFFF) / 360;
+ sp118 = coss(temp_t7) * 25.0;
+ temp_f0_3 = sins(temp_t7) * 25.0;
+ D_80162FC0[0] = temp_v0_2->posX + sp118;
+ D_80162FC0[1] = temp_v0_2->posY;
+ D_80162FC0[2] = temp_v0_2->posZ + temp_f0_3;
+ someRot = (get_angle_between_two_vectors(D_80162FB0, D_80162FC0) * 0xFFFF) / 65520;
+ break;
+ case States::STATIONARY:
+ var_f20 = CenterY + 3.5f;
+ someRot = 0;
+ break;
+
+ case States::PODIUM_CEREMONY:
+ if ((D_8016347C == 0) || (gNearestWaypointByPlayerId[3] < 5)) {
+ break;
+ } else {
+ waypoint = func_8000D2B4(var_f22, var_f20, var_f24, waypoint, 3);
+ if ((waypoint < 0) || (gWaypointCountByPathIndex[3] < waypoint)) {
+ waypoint = 0;
+ }
+ if (((s32) waypoint) < 0x1A) {
+ temp_v0_2 = &D_80164550[3][(waypoint + 1) % gWaypointCountByPathIndex[3]];
+ D_80162FB0[0] = temp_v0_2->posX;
+ D_80162FB0[1] = temp_v0_2->posY;
+ D_80162FB0[2] = temp_v0_2->posZ;
+ temp_v0_4 = &D_80164550[3][(waypoint + 2) % gWaypointCountByPathIndex[3]];
+ D_80162FC0[0] = temp_v0_4->posX;
+ D_80162FC0[1] = temp_v0_4->posY;
+ D_80162FC0[2] = temp_v0_4->posZ;
+ someRot = (get_angle_between_two_vectors(D_80162FB0, D_80162FC0) * 0xFFFF) / 65520;
+ } else {
+ D_80162FB0[0] = var_f22;
+ D_80162FB0[1] = var_f20;
+ D_80162FB0[2] = var_f24;
+ D_80162FC0[0] = -2409.197f;
+ D_80162FC0[1] = 0.0f;
+ D_80162FC0[2] = -355.254f;
+ someRot = (get_angle_between_two_vectors(D_80162FB0, D_80162FC0) * 0xFFFF) / 65520;
+ }
+ temp_f14 = ((D_80162FB0[0] + D_80162FC0[0]) * 0.5f) - var_f22;
+ temp_f16 = ((D_80162FB0[2] + D_80162FC0[2]) * 0.5f) - var_f24;
+ temp_f0_4 = sqrtf((temp_f14 * temp_f14) + (temp_f16 * temp_f16));
+ if (temp_f0_4 > 0.01f) {
+ var_f22 += (Unk_3C * temp_f14) / temp_f0_4;
+ var_f24 += (Unk_3C * temp_f16) / temp_f0_4;
+ } else {
+ var_f22 += temp_f14 / 5.0f;
+ var_f24 += temp_f16 / 5.0f;
+ }
+ var_f20 = calculate_surface_height(var_f22, 2000.0f, var_f24, _Collision.meshIndexZX) + 3.5f;
+ if (var_f20 < (-1000.0)) {
+ var_f20 = Pos[1];
+ }
+ check_bounding_collision(&_Collision, 10.0f, var_f22, var_f20, var_f24);
+ }
+ break;
+ case States::EXPLODE:
+ temp_v0_2 = &D_80164550[0][waypoint];
+ D_80162FB0[0] = temp_v0_2->posX;
+ D_80162FB0[1] = temp_v0_2->posY;
+ D_80162FB0[2] = temp_v0_2->posZ;
+ temp_v0_4 = &D_80164550[0][(waypoint + 1) % gWaypointCountByPathIndex[0]];
+ D_80162FC0[0] = temp_v0_4->posX;
+ D_80162FC0[1] = temp_v0_4->posY;
+ D_80162FC0[2] = temp_v0_4->posZ;
+ var_f20 += 3.0f - (circleTimer * 0.3f);
+ someRot = (get_angle_between_two_vectors(D_80162FB0, D_80162FC0) * 0xFFFF) / 65520;
+ break;
+ default:
+ break;
+ }
+
+ if (state == States::EXPLODE) {
+ sp108 = 2.0f * circleTimer;
+ sp118 = coss(0xFFFF - someRot) * circleTimer;
+ var_f18 = sins(0xFFFF - someRot) * circleTimer;
+ circleTimer++;
+ temp_f2_4 = (var_f20 - 2.3f) + (sp108 / 3.0f);
+ spAC = temp_f2_4;
+ spA0 = temp_f2_4;
+ sp94 = temp_f2_4;
+ sp88 = temp_f2_4;
+ if (circleTimer >= 31) {
+ state = States::DISABLED;
+ }
+ } else {
+ sp118 = coss(0xFFFF - someRot) * 1.5f;
+ var_f18 = sins(0xFFFF - someRot) * 1.5f;
+ temp_f16_2 = var_f20 - 2.3f;
+ temp_f12_3 = (bounceTimer % 3) * 0.15f;
+ temp_f14_2 = temp_f16_2 - temp_f12_3;
+ temp_f12_4 = temp_f16_2 + temp_f12_3;
+ spAC = temp_f14_2;
+ sp94 = temp_f14_2;
+ spA0 = temp_f12_4;
+ sp88 = temp_f12_4;
+ var_f20 += sins((bounceTimer * 0x13FFEC) / 360);
+ bounceTimer = (bounceTimer + 1) % 18;
+ }
+
+ WheelPos[0][0] = (sp118 - var_f18) + var_f22;
+ WheelPos[0][1] = spAC;
+ WheelPos[0][2] = (var_f18 + sp118) + var_f24;
+ WheelPos[1][0] = (var_f18 + sp118) + var_f22;
+ WheelPos[1][1] = spA0;
+ WheelPos[1][2] = (var_f18 - sp118) + var_f24;
+ WheelPos[2][0] = ((-sp118) - var_f18) + var_f22;
+ WheelPos[2][1] = sp94;
+ WheelPos[2][2] = ((-var_f18) + sp118) + var_f24;
+ WheelPos[3][0] = ((-sp118) + var_f18) + var_f22;
+ WheelPos[3][1] = sp88;
+ WheelPos[3][2] = ((-var_f18) - sp118) + var_f24;
+ Pos[0] = var_f22;
+ Pos[1] = var_f20;
+ Pos[2] = var_f24;
+ WaypointIndex = waypoint;
+ Unk_3C = unk_3C;
+ SomeRot = someRot;
+ State = state;
+ BounceTimer = bounceTimer;
+ CircleTimer = circleTimer;
+ }
+}
+
+void OBombKart::Draw(s32 cameraId) {
+
+ if (gModeSelection == BATTLE) {
+ return;
+ }
+
+ if (GetCourse() == GetPodiumCeremony()) {
+ // This isn't functionally equivallent.
+ // Technicaly it should be if (kart[0].WaypointIndex < 16)
+ if (WaypointIndex < 16) {
+ return;
+ } else {
+ cameraId = PLAYER_FOUR;
+ }
+ }
+
+ Camera* camera;
+ s32 temp_s4;
+ s32 i;
+ s32 state;
+
+ if (gGamestate == ENDING) {
+ cameraId = 0;
+ }
+ camera = &camera1[cameraId];
+ if (cameraId == PLAYER_ONE) {
+ if (is_obj_flag_status_active(ObjectIndex, 0x00200000) != 0) {
+ Unk_4A = 0;
+ } else if (gGamestate != ENDING) {
+ Unk_4A = 1;
+ }
+ set_object_flag_status_false(ObjectIndex, 0x00200000);
+ }
+
+ // huh???
+ state = State;
+ if (State != States::DISABLED) {
+ gObjectList[ObjectIndex].pos[0] = Pos[0];
+ gObjectList[ObjectIndex].pos[1] = Pos[1];
+ gObjectList[ObjectIndex].pos[2] = Pos[2];
+ temp_s4 = func_8008A364(ObjectIndex, cameraId, 0x31C4U, 0x000001F4);
+ if (is_obj_flag_status_active(ObjectIndex, VISIBLE) != 0) {
+ set_object_flag_status_true(ObjectIndex, 0x00200000);
+ D_80183E80[0] = 0;
+ D_80183E80[1] = func_800418AC(Pos[0], Pos[2], camera->pos);
+ D_80183E80[2] = 0x8000;
+ func_800563DC(ObjectIndex, cameraId, 0x000000FF);
+ OBombKart::SomeRender(camera->pos);
+ if (((u32) temp_s4 < 0x4E21U) && (state != BOMB_STATE_EXPLODED)) {
+ OBombKart::LoadMtx();
+ }
+ }
+ }
+}
+
+void OBombKart::DrawBattle(s32 cameraId) {
+ if (gModeSelection != BATTLE) {
+ return;
+ }
+ Player* temp_v0;
+ s32 temp_s1;
+ s32 playerId;
+ Object* object;
+
+ for (playerId = 0; playerId < gPlayerCount; playerId++) {
+ object = &gObjectList[ObjectIndex];
+ if (object->state != 0) {
+ temp_s1 = object->primAlpha;
+ temp_v0 = &gPlayerOne[playerId];
+ object->pos[0] = temp_v0->pos[0];
+ object->pos[1] = temp_v0->pos[1] - 2.0;
+ object->pos[2] = temp_v0->pos[2];
+ object->surfaceHeight = temp_v0->unk_074;
+ func_800563DC(ObjectIndex, cameraId, temp_s1);
+ func_8005669C(ObjectIndex, cameraId, temp_s1);
+ func_800568A0(ObjectIndex, cameraId);
+ }
+ }
+}
+
+void OBombKart::SomeRender(Vec3f arg1) {
+ D_80183E80[0] = 0;
+ D_80183E80[2] = 0x8000;
+ gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D0079C8);
+ load_texture_block_rgba16_mirror((u8*) D_0D02AA58, 0x00000010, 0x00000010);
+ D_80183E80[1] = func_800418AC(WheelPos[0][0], WheelPos[0][2], arg1);
+ func_800431B0(WheelPos[0], D_80183E80, 0.15f, (Vtx*)common_vtx_rectangle);
+ D_80183E80[1] = func_800418AC(WheelPos[1][0], WheelPos[1][2], arg1);
+ func_800431B0(WheelPos[1], D_80183E80, 0.15f, (Vtx*)common_vtx_rectangle);
+ D_80183E80[1] = func_800418AC(WheelPos[2][0], WheelPos[2][2], arg1);
+ func_800431B0(WheelPos[2], D_80183E80, 0.15f, (Vtx*)common_vtx_rectangle);
+ D_80183E80[1] = func_800418AC(WheelPos[3][0], WheelPos[3][2], arg1);
+ func_800431B0(WheelPos[3], D_80183E80, 0.15f, (Vtx*)common_vtx_rectangle);
+ gSPTexture(gDisplayListHead++, 1, 1, 0, G_TX_RENDERTILE, G_OFF);
+}
+
+void OBombKart::LoadMtx() {
+ Mat4 mat;
+
+ D_80183E50[0] = Pos[0];
+ D_80183E50[1] = CenterY + 1.0;
+ D_80183E50[2] = Pos[2];
+ set_transform_matrix(mat, _Collision.orientationVector, D_80183E50, 0U, 0.5f);
+ //convert_to_fixed_point_matrix(&gGfxPool->mtxHud[gMatrixHudCount], mat);
+
+ AddHudMatrix(mat, G_MTX_LOAD | G_MTX_NOPUSH | G_MTX_MODELVIEW);
+
+ // gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxHud[gMatrixHudCount++]),
+ // G_MTX_LOAD | G_MTX_NOPUSH | G_MTX_MODELVIEW);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D007B98);
+}
+
+void OBombKart::Waypoint(s32 screenId) {
+ s32 playerWaypoint;
+ s32 bombWaypoint;
+ s32 waypointDiff;
+
+ playerWaypoint = gNearestWaypointByPlayerId[screenId];
+ playerHUD[screenId].unk_74 = 0;
+ if ((State == States::EXPLODE) || (State == States::DISABLED)) { return; };
+ bombWaypoint = WaypointIndex;
+ waypointDiff = bombWaypoint - playerWaypoint;
+ if ((waypointDiff < -5) || (waypointDiff > 0x1E)) { return; };
+ playerHUD[screenId].unk_74 = 1;
+}
+
+void OBombKart::Collision(s32 playerId, Player* player) {
+
+}
diff --git a/src/engine/vehicles/OBombKart.h b/src/engine/vehicles/OBombKart.h
new file mode 100644
index 000000000..a857b207b
--- /dev/null
+++ b/src/engine/vehicles/OBombKart.h
@@ -0,0 +1,64 @@
+#pragma once
+
+#include <libultraship.h>
+#include "Vehicle.h"
+#include <vector>
+#include "engine/Matrix.h"
+
+extern "C" {
+#include "macros.h"
+#include "main.h"
+#include "vehicles.h"
+#include "waypoints.h"
+#include "common_structs.h"
+#include "objects.h"
+}
+
+/**
+ * Used in VS mode
+ *
+ * This differs from the other vehicle classes in that it does not get added to the standard actor list
+ * So this is sort of its own thing. Draw call in different place too.
+ */
+class OBombKart {
+private:
+ enum States : uint16_t { // 0,1,3,5
+ DISABLED,
+ CCW,
+ CW,
+ STATIONARY,
+ EXPLODE,
+ PODIUM_CEREMONY,
+ };
+
+public:
+
+ const char* Type;
+
+ Vec3f Pos;
+ Vec3f WheelPos[4]; //! @todo Turn WheelPos into a struct
+ f32 Unk_3C;
+ u16 SomeRot; // Some angle
+ u16 WaypointIndex; // The waypoint the kart circles
+ States State = States::DISABLED;
+ u16 BounceTimer = 0;
+ u16 CircleTimer = 0;
+ u16 Unk_4A = 0;
+ s16 Unk_4C = 1;
+ f32 CenterY; // Center of the circle
+ s32 ObjectIndex = 0; // Index into gObjectList
+ Collision _Collision;
+
+ // 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);
+
+ void Spawn();
+ void BeginPlay();
+ void Tick();
+ void Draw(s32 playerId);
+ void DrawBattle(s32 cameraId);
+ void Collision(s32 playerId, Player* player);
+ void SomeRender(Vec3f arg1);
+ void LoadMtx();
+ void Waypoint(s32 screenId);
+};
diff --git a/src/engine/vehicles/TankerTruck.cpp b/src/engine/vehicles/TankerTruck.cpp
index 4d4de5016..8acd7984c 100644
--- a/src/engine/vehicles/TankerTruck.cpp
+++ b/src/engine/vehicles/TankerTruck.cpp
@@ -133,7 +133,7 @@ void ATankerTruck::Tick() {
Velocity[0] = Position[0] - sp5C;
Velocity[1] = Position[1] - sp58;
Velocity[2] = Position[2] - sp54;
- struct Actor* vehicleActor = &gActorList[ActorIndex];
+ struct Actor* vehicleActor = GET_ACTOR(ActorIndex);
vehicleActor->pos[0] = Position[0];
vehicleActor->pos[1] = Position[1];
vehicleActor->pos[2] = Position[2];
diff --git a/src/engine/vehicles/Train.cpp b/src/engine/vehicles/Train.cpp
index e775563f7..a16b8b5f9 100644
--- a/src/engine/vehicles/Train.cpp
+++ b/src/engine/vehicles/Train.cpp
@@ -144,7 +144,7 @@ void ATrain::SyncComponents(TrainCarStuff* trainCar, s16 orientationY) {
struct TrainCar* trainCarActor;
//! @todo: Change actorIndex to ptr to TrainCar actor
- trainCarActor = (struct TrainCar*) &gActorList[trainCar->actorIndex];
+ trainCarActor = (struct TrainCar*) GET_ACTOR(trainCar->actorIndex);
trainCarActor->pos[0] = trainCar->position[0];
trainCarActor->pos[1] = trainCar->position[1];
trainCarActor->pos[2] = trainCar->position[2];
diff --git a/src/engine/vehicles/Truck.cpp b/src/engine/vehicles/Truck.cpp
index 06b0a5a45..139edc644 100644
--- a/src/engine/vehicles/Truck.cpp
+++ b/src/engine/vehicles/Truck.cpp
@@ -150,7 +150,7 @@ void ATruck::Tick() {
Velocity[0] = Position[0] - sp5C;
Velocity[1] = Position[1] - sp58;
Velocity[2] = Position[2] - sp54;
- struct Actor* vehicleActor = &gActorList[ActorIndex];
+ struct Actor* vehicleActor = GET_ACTOR(ActorIndex);
vehicleActor->pos[0] = Position[0];
vehicleActor->pos[1] = Position[1];
vehicleActor->pos[2] = Position[2];
diff --git a/src/engine/wasm.cpp b/src/engine/wasm.cpp
index a0bd31b23..c94e7882b 100644
--- a/src/engine/wasm.cpp
+++ b/src/engine/wasm.cpp
@@ -1,247 +1,247 @@
-extern "C" {
-#include <iwasm/include/wasm_c_api.h>
-#include <iwasm/include/wasm_export.h>
-#include <iwasm/include/lib_export.h>
-#include <iwasm/interpreter/wasm_runtime.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <dirent.h>
-}
-
-#include <fstream>
-#include <iostream>
-#include <vector>
-#include <filesystem>
-#include <functional>
-#include <main.h>
-#include <code_80091750.h>
-#include <common_data.h>
-#include <data_segment2.h>
-#include <render_objects.h>
-
-struct mod_instance {
- wasm_exec_env_t exec_env;
- char* name;
-};
-
-std::vector<mod_instance> mods_instance = {};
-
-std::vector<std::function<void()>> render_hook = {};
-
-void hook_render(wasm_exec_env_t exec_env, uint32 func1) {
- render_hook.push_back([exec_env, func1]() { wasm_runtime_call_indirect(exec_env, func1, 0, NULL); });
-}
-
-extern "C" void call_render_hook() {
- for (auto f : render_hook) {
- f();
- }
-}
-
-bool CreateDirectoryRecursive(std::string const& dirName, std::error_code& err) {
- err.clear();
- if (!std::filesystem::create_directories(dirName, err)) {
- if (std::filesystem::exists(dirName)) {
- // The folder already exists:
- err.clear();
- return true;
- }
- return false;
- }
- return true;
-}
-
-void load_mod_wasm_file(char* mod_name, char* buffer, size_t size) {
- char error_buf[128];
- wasm_module_t module;
- wasm_module_inst_t module_inst;
- wasm_exec_env_t exec_env;
- uint32_t stack_size = 8092 * 8092, heap_size = 8092 * 8;
- /* parse the WASM file from buffer and create a WASM module */
- module = wasm_runtime_load((uint8_t*) buffer, size, error_buf, sizeof(error_buf));
- printf("error? %s\n", error_buf);
-
- if (module == NULL) {
- printf("%s\n", error_buf);
- exit(-1);
- }
-
- /* create an instance of the WASM module (WASM linear memory is ready) */
- module_inst = wasm_runtime_instantiate(module, stack_size, heap_size, error_buf, sizeof(error_buf));
- if (module_inst == NULL) {
- printf("%s\n", error_buf);
- exit(-1);
- }
-
- /* lookup a WASM function by its name
- The function signature can NULL here */
-
- /* creat an execution environment to execute the WASM functions */
- exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);
- mods_instance.push_back({ exec_env, mod_name });
-}
-
-mod_instance* find_mod(char* name) {
- for (size_t i = 0; i < mods_instance.size(); i++) {
- if (strcmp(mods_instance[i].name, name) == 0) {
- return &mods_instance[i];
- }
- }
- return NULL;
-}
-
-wasm_module_inst_t get_mods_instance(char* mod_name) {
- return wasm_exec_env_get_module_inst(find_mod(mod_name)->exec_env);
-}
-
-wasm_function_inst_t mod_lookup_function(char* mod_name, char* function_name) {
- return wasm_runtime_lookup_function(get_mods_instance(mod_name), function_name);
-}
-
-bool mod_call_function_wasm(char* mod_name, char* function_name, uint32 argc, uint32 argv[]) {
- wasm_function_inst_t func = mod_lookup_function(mod_name, function_name);
- if (func == NULL) {
- printf("error to find the function\n");
- return false;
- }
-
- return wasm_runtime_call_wasm(find_mod(mod_name)->exec_env, func, 1, argv);
-}
-
-void mod_print_exception(char* mod_name) {
- printf("%s\n", wasm_runtime_get_exception(get_mods_instance(mod_name)));
-}
-
-uint32 call_extern_function(wasm_exec_env_t exec_env, char* mod_name, char* function_name, uint32 argc,
- uint32 argv_offset) {
- if (!wasm_runtime_validate_app_addr(wasm_exec_env_get_module_inst(exec_env), (uint64) argv_offset,
- (uint64) argc * 4)) {
- return false;
- }
- uint32* argv =
- (uint32*) wasm_runtime_addr_app_to_native(wasm_exec_env_get_module_inst(exec_env), (uint64) argv_offset);
- return mod_call_function_wasm(mod_name, function_name, argc, argv);
-}
-
-void post_debug_print(wasm_exec_env_t exec_env) {
- gSPDisplayList(gDisplayListHead++, (Gfx*) D_0D007EB8);
- gSPDisplayList(gDisplayListHead++, (Gfx*) D_020076E0);
- func_80093C98(1);
-}
-
-void load_debug_font_wrapper(wasm_exec_env_t exec_env) {
- load_debug_font();
-}
-
-void debug_print_str2_wrapper(wasm_exec_env_t exec_env, uint32 x, uint32 y, char* str) {
- debug_print_str2(x, y, str);
-}
-
-/* the native functions that will be exported to WASM app */
-static NativeSymbol native_symbols[] = {
- EXPORT_WASM_API_WITH_SIG(call_extern_function, "($$ii)i"), EXPORT_WASM_API_WITH_SIG(hook_render, "(i)"),
- EXPORT_WASM_API_WITH_SIG(post_debug_print, "()"), EXPORT_WASM_API_WITH_SIG2(load_debug_font, "()"),
- EXPORT_WASM_API_WITH_SIG2(debug_print_str2, "(ii$)"),
- // EXPORT_WASM_API_WITH_SIG(display_input_read, "(*)i"),
- // EXPORT_WASM_API_WITH_SIG(display_flush, "(iiii*)")
-};
-
-/* all the runtime memory allocations are retricted in the global_heap_buf array */
-static char global_heap_buf[512 * 1024];
-
-char* read_wasm_binary_to_buffer(char* path, uint32_t* size) {
- std::ifstream file;
- file.open(path, std::ios::binary);
- if (!file.is_open()) {
- perror(path);
- return NULL;
- }
-
- file.seekg(0, std::ios::end);
-
- *size = file.tellg();
-
- file.seekg(0);
-
- char* c_buffer = (char*) malloc(*size);
- file.read(c_buffer, *size);
- return c_buffer;
-}
-
-extern "C" void load_wasm() {
- printf("load wasm\n");
- char* buffer;
-
- /* initialize the wasm runtime by default configurations */
- wasm_runtime_init();
-
- RuntimeInitArgs init_args;
- memset(&init_args, 0, sizeof(RuntimeInitArgs));
-
- /* configure the memory allocator for the runtime */
- init_args.mem_alloc_type = Alloc_With_Pool;
- init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
- init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
-
- /* set maximum thread number if needed when multi-thread is enabled,
- the default value is 4 */
- init_args.max_thread_num = 4;
-
- /* initialize runtime environment with user configurations*/
- if (!wasm_runtime_full_init(&init_args)) {
- exit(-1);
- }
-
- int n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol);
- if (!wasm_runtime_register_natives("env", native_symbols, n_native_symbols)) {
- exit(-1);
- }
- uint32_t size;
-
- std::error_code err;
- if (!CreateDirectoryRecursive("mods", err)) {
- // Report the error:
- std::cout << "CreateDirectoryRecursive FAILED, err: " << err.message() << std::endl;
- }
-
- /* read WASM file into a memory buffer */
- for (const auto& entry : std::filesystem::directory_iterator("mods")) {
- if (std::filesystem::is_regular_file(entry) && entry.path().extension() == ".wasm") {
- std::string path = entry.path().string();
- std::string name = entry.path().stem().string();
- printf("found %s\n", name.c_str());
- buffer = read_wasm_binary_to_buffer((char*) path.c_str(), &size);
- if (buffer == NULL) {
- printf("error read binary\n");
- }
- load_mod_wasm_file((char*) name.c_str(), buffer, size);
- mod_call_function_wasm((char*) name.c_str(), "init", 0, NULL);
- }
- }
- // buffer = read_wasm_binary_to_buffer("test.wasm", &size);
- // if (buffer == NULL) {
- // printf("error read binary\n");
- // exit(-1);
- // }
-
- // load_mod_wasm_file("test", buffer, size);
-
- // uint32_t argv[2];
-
- // /* arguments are always transferred in 32-bit element */
- // argv[0] = 8;
- // printf("run fib function\n");
- // /* call the WASM function */
- // if (mod_call_function_wasm("test", "fib", 1, argv)) {
- // /* the return value is stored in argv[0] */
- // printf("fib function return: %d\n", argv[0]);
- // } else {
- // /* exception is thrown if call fails */
- // // wasm_runtime_dump_call_stack(exec_env);
- // mod_print_exception("test");
- // }
- // mod_call_function_wasm("test", "init", 0, NULL);
- // exit(-1);
-} \ No newline at end of file
+// extern "C" {
+// #include <iwasm/include/wasm_c_api.h>
+// #include <iwasm/include/wasm_export.h>
+// #include <iwasm/include/lib_export.h>
+// #include <iwasm/interpreter/wasm_runtime.h>
+// #include <stdint.h>
+// #include <stdio.h>
+// #include <stdlib.h>
+// #include <sys/stat.h>
+// #include <dirent.h>
+// }
+
+// #include <fstream>
+// #include <iostream>
+// #include <vector>
+// #include <filesystem>
+// #include <functional>
+// #include <main.h>
+// #include <code_80091750.h>
+// #include <common_data.h>
+// #include <data_segment2.h>
+// #include <render_objects.h>
+
+// struct mod_instance {
+// wasm_exec_env_t exec_env;
+// char* name;
+// };
+
+// std::vector<mod_instance> mods_instance = {};
+
+// std::vector<std::function<void()>> render_hook = {};
+
+// void hook_render(wasm_exec_env_t exec_env, uint32 func1) {
+// render_hook.push_back([exec_env, func1]() { wasm_runtime_call_indirect(exec_env, func1, 0, NULL); });
+// }
+
+// extern "C" void call_render_hook() {
+// for (auto f : render_hook) {
+// f();
+// }
+// }
+
+// bool CreateDirectoryRecursive(std::string const& dirName, std::error_code& err) {
+// err.clear();
+// if (!std::filesystem::create_directories(dirName, err)) {
+// if (std::filesystem::exists(dirName)) {
+// // The folder already exists:
+// err.clear();
+// return true;
+// }
+// return false;
+// }
+// return true;
+// }
+
+// void load_mod_wasm_file(char* mod_name, char* buffer, size_t size) {
+// char error_buf[128];
+// wasm_module_t module;
+// wasm_module_inst_t module_inst;
+// wasm_exec_env_t exec_env;
+// uint32_t stack_size = 8092 * 8092, heap_size = 8092 * 8;
+// /* parse the WASM file from buffer and create a WASM module */
+// module = wasm_runtime_load((uint8_t*) buffer, size, error_buf, sizeof(error_buf));
+// printf("error? %s\n", error_buf);
+
+// if (module == NULL) {
+// printf("%s\n", error_buf);
+// exit(-1);
+// }
+
+// /* create an instance of the WASM module (WASM linear memory is ready) */
+// module_inst = wasm_runtime_instantiate(module, stack_size, heap_size, error_buf, sizeof(error_buf));
+// if (module_inst == NULL) {
+// printf("%s\n", error_buf);
+// exit(-1);
+// }
+
+// /* lookup a WASM function by its name
+// The function signature can NULL here */
+
+// /* creat an execution environment to execute the WASM functions */
+// exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);
+// mods_instance.push_back({ exec_env, mod_name });
+// }
+
+// mod_instance* find_mod(char* name) {
+// for (size_t i = 0; i < mods_instance.size(); i++) {
+// if (strcmp(mods_instance[i].name, name) == 0) {
+// return &mods_instance[i];
+// }
+// }
+// return NULL;
+// }
+
+// wasm_module_inst_t get_mods_instance(char* mod_name) {
+// return wasm_exec_env_get_module_inst(find_mod(mod_name)->exec_env);
+// }
+
+// wasm_function_inst_t mod_lookup_function(char* mod_name, char* function_name) {
+// return wasm_runtime_lookup_function(get_mods_instance(mod_name), function_name);
+// }
+
+// bool mod_call_function_wasm(char* mod_name, char* function_name, uint32 argc, uint32 argv[]) {
+// wasm_function_inst_t func = mod_lookup_function(mod_name, function_name);
+// if (func == NULL) {
+// printf("error to find the function\n");
+// return false;
+// }
+
+// return wasm_runtime_call_wasm(find_mod(mod_name)->exec_env, func, 1, argv);
+// }
+
+// void mod_print_exception(char* mod_name) {
+// printf("%s\n", wasm_runtime_get_exception(get_mods_instance(mod_name)));
+// }
+
+// uint32 call_extern_function(wasm_exec_env_t exec_env, char* mod_name, char* function_name, uint32 argc,
+// uint32 argv_offset) {
+// if (!wasm_runtime_validate_app_addr(wasm_exec_env_get_module_inst(exec_env), (uint64) argv_offset,
+// (uint64) argc * 4)) {
+// return false;
+// }
+// uint32* argv =
+// (uint32*) wasm_runtime_addr_app_to_native(wasm_exec_env_get_module_inst(exec_env), (uint64) argv_offset);
+// return mod_call_function_wasm(mod_name, function_name, argc, argv);
+// }
+
+// void post_debug_print(wasm_exec_env_t exec_env) {
+// gSPDisplayList(gDisplayListHead++, (Gfx*) D_0D007EB8);
+// gSPDisplayList(gDisplayListHead++, (Gfx*) D_020076E0);
+// func_80093C98(1);
+// }
+
+// void load_debug_font_wrapper(wasm_exec_env_t exec_env) {
+// load_debug_font();
+// }
+
+// void debug_print_str2_wrapper(wasm_exec_env_t exec_env, uint32 x, uint32 y, char* str) {
+// debug_print_str2(x, y, str);
+// }
+
+// /* the native functions that will be exported to WASM app */
+// static NativeSymbol native_symbols[] = {
+// EXPORT_WASM_API_WITH_SIG(call_extern_function, "($$ii)i"), EXPORT_WASM_API_WITH_SIG(hook_render, "(i)"),
+// EXPORT_WASM_API_WITH_SIG(post_debug_print, "()"), EXPORT_WASM_API_WITH_SIG2(load_debug_font, "()"),
+// EXPORT_WASM_API_WITH_SIG2(debug_print_str2, "(ii$)"),
+// // EXPORT_WASM_API_WITH_SIG(display_input_read, "(*)i"),
+// // EXPORT_WASM_API_WITH_SIG(display_flush, "(iiii*)")
+// };
+
+// /* all the runtime memory allocations are retricted in the global_heap_buf array */
+// static char global_heap_buf[512 * 1024];
+
+// char* read_wasm_binary_to_buffer(char* path, uint32_t* size) {
+// std::ifstream file;
+// file.open(path, std::ios::binary);
+// if (!file.is_open()) {
+// perror(path);
+// return NULL;
+// }
+
+// file.seekg(0, std::ios::end);
+
+// *size = file.tellg();
+
+// file.seekg(0);
+
+// char* c_buffer = (char*) malloc(*size);
+// file.read(c_buffer, *size);
+// return c_buffer;
+// }
+
+// extern "C" void load_wasm() {
+// printf("load wasm\n");
+// char* buffer;
+
+// /* initialize the wasm runtime by default configurations */
+// wasm_runtime_init();
+
+// RuntimeInitArgs init_args;
+// memset(&init_args, 0, sizeof(RuntimeInitArgs));
+
+// /* configure the memory allocator for the runtime */
+// init_args.mem_alloc_type = Alloc_With_Pool;
+// init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
+// init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
+
+// /* set maximum thread number if needed when multi-thread is enabled,
+// the default value is 4 */
+// init_args.max_thread_num = 4;
+
+// /* initialize runtime environment with user configurations*/
+// if (!wasm_runtime_full_init(&init_args)) {
+// exit(-1);
+// }
+
+// int n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol);
+// if (!wasm_runtime_register_natives("env", native_symbols, n_native_symbols)) {
+// exit(-1);
+// }
+// uint32_t size;
+
+// std::error_code err;
+// if (!CreateDirectoryRecursive("mods", err)) {
+// // Report the error:
+// std::cout << "CreateDirectoryRecursive FAILED, err: " << err.message() << std::endl;
+// }
+
+// /* read WASM file into a memory buffer */
+// for (const auto& entry : std::filesystem::directory_iterator("mods")) {
+// if (std::filesystem::is_regular_file(entry) && entry.path().extension() == ".wasm") {
+// std::string path = entry.path().string();
+// std::string name = entry.path().stem().string();
+// printf("found %s\n", name.c_str());
+// buffer = read_wasm_binary_to_buffer((char*) path.c_str(), &size);
+// if (buffer == NULL) {
+// printf("error read binary\n");
+// }
+// load_mod_wasm_file((char*) name.c_str(), buffer, size);
+// mod_call_function_wasm((char*) name.c_str(), "init", 0, NULL);
+// }
+// }
+// // buffer = read_wasm_binary_to_buffer("test.wasm", &size);
+// // if (buffer == NULL) {
+// // printf("error read binary\n");
+// // exit(-1);
+// // }
+
+// // load_mod_wasm_file("test", buffer, size);
+
+// // uint32_t argv[2];
+
+// // /* arguments are always transferred in 32-bit element */
+// // argv[0] = 8;
+// // printf("run fib function\n");
+// // /* call the WASM function */
+// // if (mod_call_function_wasm("test", "fib", 1, argv)) {
+// // /* the return value is stored in argv[0] */
+// // printf("fib function return: %d\n", argv[0]);
+// // } else {
+// // /* exception is thrown if call fails */
+// // // wasm_runtime_dump_call_stack(exec_env);
+// // mod_print_exception("test");
+// // }
+// // mod_call_function_wasm("test", "init", 0, NULL);
+// // exit(-1);
+// } \ No newline at end of file