Refactor Track Class To Instantiate On Track Load (#587)

* Initial Commit

* First compilation of Registry template

* Further changes

* wip changes

* Impl TrackBrowser and Registry Info

* Remove const from TInfo

* Prep GetWorld

* Name refactor

* Refactor gWorldInstance to GetWorld()

* wip

* Should work now

* Data menu work again

* Fix editor staying open after program close

* Rename LoadLevel to LoadTrackDataFromJson

* More changes

* Add statue

* Add search to content browser using tags

* Fix statue pos and register tags

* Fix actor loading

* Fix delete all bug which deleted cameras

* reduce some boiler plate in actor and object

* Remove unused rulesets

* Search bar for all tabs

* fix data screen

* fix actor spawning

* temp editor fix

* Clean up

* improve extra mode transformation

* fix podium crash

* Fix editor clicking

* Fix editor clicking 2

* fix extra in custom track

* Fix FI for three actors

* Fix divide by zero error

* Ids managed by Registry

* Add scary comment

---------

Co-authored-by: MegaMech <7255464+MegaMech@users.noreply.github.com>
Co-authored-by: coco875 <pereira.jannin@gmail.com>
This commit is contained in:
MegaMech 2025-12-13 11:50:28 -07:00 committed by GitHub
parent e6acb59ef4
commit b934e98fc3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
157 changed files with 2623 additions and 2473 deletions

View File

@ -5,7 +5,6 @@ Checks: '
performance-*,
bugprone-*,
cppcoreguidelines-*,
llvm-include-order,
-readability-magic-numbers,
-readability-identifier-length,
@ -54,13 +53,6 @@ CheckOptions:
- key: readability-identifier-naming.NamespaceCase
value: CamelCase
# Functions: PascalCase (C++ style)
- key: readability-identifier-naming.FunctionCase
value: lower_case
# Allow legacy decompilation function names (func_XXXXXXXX)
- key: readability-identifier-naming.FunctionIgnoredRegexp
value: '^func_[0-9A-Fa-f]+$'
# Methods: PascalCase
- key: readability-identifier-naming.MethodCase
value: CamelCase

View File

@ -56,8 +56,6 @@ typedef enum {
/* 0x15 */ NUM_TRACKS
} TRACKS;
#define TRACK_NULL 0xFF
typedef enum {
/* 0x00 */ TIME_TRIAL_DATA_LUIGI_RACEWAY,
/* 0x01 */ TIME_TRIAL_DATA_MOO_MOO_FARM,

View File

@ -16,6 +16,7 @@
#include <stdbool.h>
#include "port/Game.h"
#include "port/audio/HMAS.h"
#include "engine/TrackBrowser.h"
s8 D_8018EF10;
UnkStruct8018EF18 D_8018EF18[16];
@ -3544,7 +3545,7 @@ void func_800CAEC4(u8 playerId, f32 arg1) {
D_800EA120[playerId] = arg1;
//! @warning this used to be gCurrentCourseId + 0x19007020
// This may not be equivallent.
play_sound(GetTrackIndex() + 0x19007020, &D_800E9F7C[playerId].pos, playerId, &D_800EA1D4,
play_sound(TrackBrowser_GetTrackIndex() + 0x19007020, &D_800E9F7C[playerId].pos, playerId, &D_800EA1D4,
&D_800EA120[playerId], (u8*) &D_800E9F7C[playerId].unk_14);
break;
default:

View File

@ -309,7 +309,7 @@ void freecam_init(Vec3f pos, s16 rot, u32 mode, s32 cameraId) {
} else {
// gCameraFOV[cameraId] = 40.0f;
}
camera->unk_B4 = gCameraFOV[0];
camera->unk_B4 = gCameraFOV[cameraId];
// }
// if (D_80164678[cameraId] == 1) {
// if (D_80164A28 == 1) {

View File

@ -4,6 +4,7 @@
#include <stubs.h>
#include "code_800029B0.h"
#include "TrackBrowser.h"
#include "memory.h"
#include "waypoints.h"
#include "actors.h"
@ -27,17 +28,18 @@
#include <assets/models/tracks/mario_raceway/mario_raceway_data.h>
#include <assets/models/tracks/moo_moo_farm/moo_moo_farm_data.h>
#include "port/Game.h"
#include "engine/CoreMath.h"
extern s32 D_802BA038;
extern s16 D_802BA048;
s16 gCurrentCourseId = 0;
s16 gCurrentlyLoadedCourseId = 0xFF;
uintptr_t gCurrentlyLoadedTrackAddr = NULL;
u16 D_800DC5A8 = 0;
s32 D_800DC5AC = 0;
u16 D_800DC5B0 = 1;
u16 D_800DC5B4 = 0;
u16 D_800DC5B8 = 0;
u16 D_800DC5BC = 0;
bool bFog = false;
u16 gIsInQuitToMenuTransition = 0;
u16 gQuitToMenuTransitionCounter = 0;
u16 D_800DC5C8 = 0;
@ -61,14 +63,10 @@ ScreenContext* gScreenTwoCtx = &gScreenContexts[1];
ScreenContext* gScreenThreeCtx = &gScreenContexts[2];
ScreenContext* gScreenFourCtx = &gScreenContexts[3];
u16 gIsGamePaused = false; // true if the game is paused and false if the game is not paused
bool gIsEditorPaused = true;
u8* pAppNmiBuffer = (u8*) &osAppNmiBuffer;
s32 gIsMirrorMode = 0;
void set_mirror_mode(s32 mirror) {
if (gIsMirrorMode != mirror) {
UnLoadTrack();
}
gIsMirrorMode = mirror;
}
Vec3f gVtxStretch = {1.0f, 1.0f, 1.0f};
@ -163,9 +161,7 @@ UNUSED u8 D_80162578[sizeof(struct Actor)];
s16 gDebugPathCount;
s16 sIsController1Unplugged;
s32 D_801625EC;
s32 D_801625F0;
s32 D_801625F4;
struct RGBA8 gFogColour;
uintptr_t D_801625F8;
f32 D_801625FC;
@ -209,13 +205,13 @@ void setup_race(void) {
gCurrentCourseId = gCupCourseOrder[gCupSelection][gCourseIndexInCup];
// Skip for debug menu
if (gMenuSelection != START_MENU) {
SetTrackFromCup();
TrackBrowser_SetTrackFromCup();
}
}
gActiveScreenMode = gScreenModeSelection;
if (gCurrentCourseId != gCurrentlyLoadedCourseId) {
if (CM_GetTrack() != gCurrentlyLoadedTrackAddr) {
D_80150120 = 0;
gCurrentlyLoadedCourseId = gCurrentCourseId;
gCurrentlyLoadedTrackAddr = CM_GetTrack();
gNextFreeMemoryAddress = gFreeMemoryResetAnchor;
load_track(gCurrentCourseId);
gFreeMemoryCourseAnchor = gNextFreeMemoryAddress;
@ -259,7 +255,7 @@ void setup_race(void) {
if (!gDemoMode) {
//! @warning this used to be gCurrentCourseId + 4
// Hopefully this is equivallent.
func_800CA008(gPlayerCountSelection1 - 1, GetTrackIndex() + 4);
func_800CA008(gPlayerCountSelection1 - 1, TrackBrowser_GetTrackIndex() + 4);
func_800CB2C4();
}
@ -284,9 +280,9 @@ void setup_editor(void) {
}
gActiveScreenMode = gScreenModeSelection;
if (gCurrentCourseId != gCurrentlyLoadedCourseId) {
if (CM_GetTrack() != gCurrentlyLoadedTrackAddr) {
D_80150120 = 0;
gCurrentlyLoadedCourseId = gCurrentCourseId;
gCurrentlyLoadedTrackAddr = CM_GetTrack();
gNextFreeMemoryAddress = gFreeMemoryResetAnchor;
load_track(gCurrentCourseId);
gFreeMemoryCourseAnchor = gNextFreeMemoryAddress;
@ -344,7 +340,7 @@ void credits_spawn_actors(void) {
Vec3f velocity = { 0, 0, 0 };
Vec3s rotation = { 0, 0, 0 };
D_800DC5BC = 0;
bFog = false;
D_800DC5C8 = 0;
gNumActors = 0;
set_mirror_mode(0);

View File

@ -5,6 +5,7 @@
#include <libultraship.h>
#include <actor_types.h>
#include "camera.h"
#include "engine/CoreMath.h"
typedef struct {
/* 0x00 */ struct Controller* controllers; // gControllers ptr 800F6910
@ -40,13 +41,13 @@ void clear_nmi_buffer(void);
void credits_spawn_actors(void);
extern s16 gCurrentCourseId; // D_800DC5A0
extern s16 gCurrentlyLoadedCourseId;
extern uintptr_t gCurrentlyLoadedTrackAddr;
extern u16 D_800DC5A8;
extern s32 D_800DC5AC;
extern u16 D_800DC5B0;
extern u16 D_800DC5B4;
extern u16 D_800DC5B8;
extern u16 D_800DC5BC;
extern bool bFog;
extern u16 gIsInQuitToMenuTransition;
extern u16 gQuitToMenuTransitionCounter;
extern u16 D_800DC5C8;
@ -66,7 +67,6 @@ extern ScreenContext* gScreenTwoCtx;
extern ScreenContext* gScreenThreeCtx;
extern ScreenContext* gScreenFourCtx;
extern u16 gIsGamePaused;
extern bool gIsEditorPaused;
extern u8* pAppNmiBuffer;
extern s32 gIsMirrorMode; // D_800DC604
extern void set_mirror_mode(s32 mirror);
@ -153,9 +153,7 @@ extern u16 gNumPermanentActors;
extern UNUSED u8 D_80162578[];
extern s16 gDebugPathCount;
extern s16 sIsController1Unplugged;
extern s32 D_801625EC;
extern s32 D_801625F0;
extern s32 D_801625F4;
extern struct RGBA8 gFogColour;
extern uintptr_t D_801625F8;
extern f32 D_801625FC;

View File

@ -3738,12 +3738,12 @@ void load_track_path(s32 pathIndex) {
var_v0 = func_80011014(pathDest, path, sp24, pathIndex);
gPathCountByPathIndex[pathIndex] = (u16) var_v0;
} else {
printf("PathTable is invalid. It has %d path points\n It may also be missing the end tag.\n", i);
printf("[code_80005FD0] [load_track_path] PathTable is invalid. It has %d path points\n It may also be missing the end tag.\n", i);
}
} else { // ALL TRACKS
TrackPathPoint* pathSrc = CM_GetProps()->PathTable2[pathIndex];
if (pathSrc == NULL) {
printf("code_80005FD0.c: Path %d in Track::PathTable2, was NULL.\n Your track is missing a path\n",
printf("[code_80005FD0] [load_track_path] Path %d in Track::PathTable2, was NULL.\n Your track is missing a path\n",
pathIndex);
}

View File

@ -39,6 +39,7 @@
#include <assets/textures/some_data.h>
#include "port/Game.h"
#include "engine/Matrix.h"
#include "engine/editor/Editor.h"
#include "port/interpolation/FrameInterpolation.h"
//! @warning this macro is undef'd at the end of this file
@ -1023,7 +1024,7 @@ void func_80059A88(s32 playerId) {
void func_80059AC8(void) {
s32 i;
if ((gIsGamePaused == false) && (gIsEditorPaused == false)) {
if ((gIsGamePaused == false) && (Editor_IsPaused() == false)) {
func_8008C1D8(&D_80165678);
gRaceFrameCounter++;
for (i = 0; i < gPlayerCount; i++) {
@ -1189,7 +1190,7 @@ void func_8005A070(void) {
gMatrixHudCount = 0;
D_801655C0 = 0;
func_80041D34();
if (gIsGamePaused == false && (gIsEditorPaused == false)) {
if (gIsGamePaused == false && (Editor_IsPaused() == false)) {
func_8005C728();
if (gGamestate == ENDING) {
// func_80086604();
@ -1367,7 +1368,7 @@ void func_8005A99C(void) {
if (gPlayerCountSelection1 == 3) {
D_801657E8 = true;
}
if (CVarGetInteger("gEditorEnabled", 0) == false) {
if (Editor_IsEnabled() == false) {
gIsHUDVisible = (s32) 1;
}
D_8018D170 = (s32) 1;

View File

@ -29,7 +29,7 @@
#include <assets/textures/boo_frames.h>
#include "port/Game.h"
#include "port/Engine.h"
#include "engine/editor/Editor.h"
#include "engine/tracks/Track.h"
void init_hud(void) {
@ -237,7 +237,7 @@ void func_8006F824(s32 arg0) {
D_80165828 = D_801657F8;
D_80165832[0] = D_80165800[0];
D_80165832[1] = D_80165800[1];
if ((arg0 != 0) && (gIsGamePaused == 0) && (gIsEditorPaused == false)) {
if ((arg0 != 0) && (gIsGamePaused == 0) && (Editor_IsPaused() == false)) {
play_sound2(SOUND_ACTION_PING);
}
}

View File

@ -24,6 +24,7 @@
#include "render_courses.h"
#include "main.h"
#include "render_player.h"
#include "engine/TrackBrowser.h"
#include "engine/tracks/Track.h"
#include "engine/Matrix.h"
@ -65,7 +66,7 @@ void func_80280038(Camera* camera) {
gSPMatrix(gDisplayListHead++, camera->lookAtMatrix,
G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
gCurrentCourseId = gCreditsCourseId;
SetTrackById(gCreditsCourseId);
TrackBrowser_SetTrackByIdx(gCreditsCourseId);
mtxf_identity(matrix);
render_set_position(matrix, 0);
render_track(gScreenOneCtx);
@ -148,7 +149,7 @@ void load_credits(void) {
gCurrentCourseId = gCreditsCourseId;
SetTrackById(gCreditsCourseId);
TrackBrowser_SetTrackByIdx(gCreditsCourseId);
D_800DC5B4 = 1;
func_802A4D18();
set_screen();
@ -173,7 +174,7 @@ void load_credits(void) {
D_8015F5A0 = 0;
D_8015F58C = 0;
gCollisionMeshCount = 0;
D_800DC5BC = 0;
bFog = false;
D_800DC5C8 = 0;
gCollisionMesh = (CollisionTriangle*) gNextFreeMemoryAddress;
camera->pos[0] = 1400.0f;

View File

@ -129,7 +129,7 @@ void setup_podium_ceremony(void) {
D_8015F5A0 = 0;
D_8015F58C = 0;
gCollisionMeshCount = (u16) 0;
D_800DC5BC = (u16) 0;
bFog = false;
D_800DC5C8 = (u16) 0;
gCollisionMesh = (CollisionTriangle*) gNextFreeMemoryAddress;
//! @bug these segmented addresses need to be symbols for mobility

View File

@ -21,7 +21,7 @@ AActor::AActor(SpawnParams params) {
void AActor::BeginPlay() {
// This makes actors clickable in the editor
if (CVarGetInteger("gEditorEnabled", false) == true) {
if (Editor_IsEnabled()) {
if ((nullptr != Model) && (Model[0] != '\0')) {
// Prevent collision mesh from being generated extra times.
if (Triangles.size() == 0) {

View File

@ -11,6 +11,7 @@
#include "actors/Ship.h"
#include "actors/Tree.h"
#include "actors/Text.h"
#include "actors/BowserStatue.h"
#include "vehicles/Train.h"
#include "vehicles/Boat.h"
#include "vehicles/Bus.h"

25
src/engine/AllTracks.h Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include "engine/tracks/Track.h"
#include "engine/tracks/MarioRaceway.h"
#include "engine/tracks/ChocoMountain.h"
#include "engine/tracks/BowsersCastle.h"
#include "engine/tracks/BansheeBoardwalk.h"
#include "engine/tracks/YoshiValley.h"
#include "engine/tracks/FrappeSnowland.h"
#include "engine/tracks/KoopaTroopaBeach.h"
#include "engine/tracks/RoyalRaceway.h"
#include "engine/tracks/LuigiRaceway.h"
#include "engine/tracks/MooMooFarm.h"
#include "engine/tracks/ToadsTurnpike.h"
#include "engine/tracks/KalimariDesert.h"
#include "engine/tracks/SherbetLand.h"
#include "engine/tracks/RainbowRoad.h"
#include "engine/tracks/WarioStadium.h"
#include "engine/tracks/BlockFort.h"
#include "engine/tracks/Skyscraper.h"
#include "engine/tracks/DoubleDeck.h"
#include "engine/tracks/DKJungle.h"
#include "engine/tracks/BigDonut.h"
#include "engine/tracks/TestTrack.h"

View File

@ -1,18 +1,19 @@
#include "Cup.h"
#include "tracks/Track.h"
#include "port/Game.h"
Cup::Cup(std::string id, const char* name, std::vector<std::shared_ptr<Track>> courses) {
Cup::Cup(std::string id, const char* name, std::vector<std::string> tracks) {
Id = id;
Name = name;
Courses = courses;
mTracks = tracks;
if (Courses.size() != 4) {
throw std::invalid_argument("A cup must contain exactly 4 courses.");
if (mTracks.size() != 4) {
throw std::invalid_argument("A cup must contain exactly 4 tracks.");
}
}
void Cup::Next() {
if (CursorPosition < Courses.size() - 1) {
if (CursorPosition < mTracks.size() - 1) {
CursorPosition++;
}
}
@ -24,23 +25,23 @@ void Cup::Previous() {
}
void Cup::SetTrack(size_t position) {
if ((position < 0) || (position >= Courses.size())) {
if ((position < 0) || (position >= mTracks.size())) {
throw std::invalid_argument("Invalid track index.");
}
CursorPosition = position;
}
std::shared_ptr<Track> Cup::GetTrack() {
return Courses[CursorPosition];
std::string Cup::GetTrack() {
return mTracks[CursorPosition];
}
size_t Cup::GetSize() {
return Courses.size();
return mTracks.size();
}
// Function to shuffle the courses randomly
void Cup::ShuffleCourses() {
// Function to shuffle the tracks randomly
void Cup::ShuffleTracks() {
// std::random_device rd;
// std::mt19937 g(rd());
//std::shuffle(Courses.begin(), Courses.end(), g);
//std::shuffle(mTracks.begin(), mTracks.end(), g);
}

View File

@ -13,15 +13,15 @@ public:
const char* Name;
u8 *Thumbnail;
size_t CursorPosition = 0; // Track index in cup
std::vector<std::shared_ptr<Track>> Courses;
std::vector<std::string> mTracks;
explicit Cup(std::string id, const char* name, std::vector<std::shared_ptr<Track>> courses);
explicit Cup(std::string id, const char* name, std::vector<std::string> tracks);
virtual void ShuffleCourses();
virtual void ShuffleTracks();
virtual void Next();
virtual void Previous();
virtual void SetTrack(size_t position);
virtual std::shared_ptr<Track> GetTrack();
virtual std::string GetTrack();
virtual size_t GetSize();
};
};

View File

@ -11,12 +11,11 @@ void RunGarbageCollector() {
}
void CleanActors() {
for (auto actor = gWorldInstance.Actors.begin(); actor != gWorldInstance.Actors.end();) {
AActor* act = *actor; // Get a mutable copy
for (auto actor = GetWorld()->Actors.begin(); actor != GetWorld()->Actors.end();) {
auto* act = actor->get(); // Get a mutable copy
if (act->bPendingDestroy) {
if (act->IsMod()) { // C++ actor
delete act;
actor = gWorldInstance.Actors.erase(actor); // Remove from container
actor = GetWorld()->Actors.erase(actor); // Remove from container
} else { // Old C actor
act->Flags = 0;
act->Type = 0;
@ -32,11 +31,10 @@ void CleanActors() {
}
void CleanStaticMeshActors() {
for (auto actor = gWorldInstance.StaticMeshActors.begin(); actor != gWorldInstance.StaticMeshActors.end();) {
StaticMeshActor* act = *actor; // Get a mutable copy
for (auto actor = GetWorld()->StaticMeshActors.begin(); actor != GetWorld()->StaticMeshActors.end();) {
StaticMeshActor* act = actor->get(); // Get a mutable copy
if (act->bPendingDestroy) {
delete act;
actor = gWorldInstance.StaticMeshActors.erase(actor); // Remove from container
actor = GetWorld()->StaticMeshActors.erase(actor); // Remove from container
continue;
} else {
actor++;
@ -45,11 +43,10 @@ void CleanStaticMeshActors() {
}
void CleanObjects() {
for (auto object = gWorldInstance.Objects.begin(); object != gWorldInstance.Objects.end();) {
OObject* obj = *object; // Get a mutable copy
for (auto object = GetWorld()->Objects.begin(); object != GetWorld()->Objects.end();) {
OObject* obj = object->get(); // Get a mutable copy
if (obj->bPendingDestroy) {
delete obj;
object = gWorldInstance.Objects.erase(object); // Remove from container
object = GetWorld()->Objects.erase(object); // Remove from container
continue;
}
object++;

View File

@ -59,14 +59,14 @@ void SetTextMatrix(Mat4 mf, f32 x, f32 y, f32 arg3, f32 arg4) {
// AddMatrix but with custom gfx ptr arg and flags are predefined
Gfx* AddTextMatrix(Gfx* displayListHead, Mat4 mtx) {
// Push a new matrix to the stack
gWorldInstance.Mtx.Objects.emplace_back();
GetWorld()->Mtx.Objects.emplace_back();
// Convert to a fixed-point matrix
FrameInterpolation_RecordMatrixMtxFToMtx((MtxF*)mtx, &gWorldInstance.Mtx.Objects.back());
guMtxF2L(mtx, &gWorldInstance.Mtx.Objects.back());
FrameInterpolation_RecordMatrixMtxFToMtx((MtxF*)mtx, &GetWorld()->Mtx.Objects.back());
guMtxF2L(mtx, &GetWorld()->Mtx.Objects.back());
// Load the matrix
gSPMatrix(displayListHead++, &gWorldInstance.Mtx.Objects.back(), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPMatrix(displayListHead++, &GetWorld()->Mtx.Objects.back(), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
return displayListHead;
}
@ -195,43 +195,43 @@ void AddLocalRotation(Mat4 mat, IRotator rot) {
extern "C" {
void AddHudMatrix(Mat4 mtx, s32 flags) {
AddMatrix(gWorldInstance.Mtx.Objects, mtx, flags);
AddMatrix(GetWorld()->Mtx.Objects, mtx, flags);
}
Mtx* GetScreenMatrix(void) {
return &gWorldInstance.Mtx.Screen2D;
return &GetWorld()->Mtx.Screen2D;
}
Mtx* GetOrthoMatrix(void) {
return &gWorldInstance.Mtx.Ortho;
return &GetWorld()->Mtx.Ortho;
}
Mtx* GetPerspMatrix(size_t cameraId) {
return &gWorldInstance.Mtx.Persp[cameraId];
return &GetWorld()->Mtx.Persp[cameraId];
}
Mtx* GetLookAtMatrix(size_t cameraId) {
return &gWorldInstance.Mtx.LookAt[cameraId];
return &GetWorld()->Mtx.LookAt[cameraId];
}
void AddObjectMatrix(Mat4 mtx, s32 flags) {
AddMatrix(gWorldInstance.Mtx.Objects, mtx, flags);
AddMatrix(GetWorld()->Mtx.Objects, mtx, flags);
}
Mtx* GetShadowMatrix(size_t playerId) {
return &gWorldInstance.Mtx.Shadows[playerId];
return &GetWorld()->Mtx.Shadows[playerId];
}
Mtx* GetKartMatrix(size_t playerId) {
return &gWorldInstance.Mtx.Karts[playerId];
return &GetWorld()->Mtx.Karts[playerId];
}
void AddEffectMatrix(Mat4 mtx, s32 flags) {
AddMatrix(gWorldInstance.Mtx.Objects, mtx, flags);
AddMatrix(GetWorld()->Mtx.Objects, mtx, flags);
}
void AddEffectMatrixOrtho(void) {
auto& stack = gWorldInstance.Mtx.Objects;
auto& stack = GetWorld()->Mtx.Objects;
stack.emplace_back();
guOrtho(&stack.back(), 0.0f, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, 0.0f, -100.0f, 100.0f, 1.0f);
@ -240,7 +240,7 @@ extern "C" {
}
Mtx* GetEffectMatrix(void) {
return GetMatrix(gWorldInstance.Mtx.Objects);
return GetMatrix(GetWorld()->Mtx.Objects);
}
@ -249,14 +249,14 @@ extern "C" {
* We might need to adjust which ones we clear.
*/
void ClearMatrixPools(void) {
gWorldInstance.Mtx.Objects.clear();
// gWorldInstance.Mtx.Shadows.clear();
//gWorldInstance.Mtx.Karts.clear();
// gWorldInstance.Mtx.Effects.clear();
GetWorld()->Mtx.Objects.clear();
// GetWorld()->Mtx.Shadows.clear();
//GetWorld()->Mtx.Karts.clear();
// GetWorld()->Mtx.Effects.clear();
}
void ClearObjectsMatrixPool(void) {
gWorldInstance.Mtx.Objects.clear();
GetWorld()->Mtx.Objects.clear();
}
}

View File

@ -36,4 +36,4 @@ void AddKartMatrix(Mat4 mtx, s32 flags);
}
#endif
#endif // _MATRIX_HEADER_
#endif // _MATRIX_HEADER_

View File

@ -52,15 +52,11 @@ extern "C" void add_triangle_to_collision_mesh(Vtx* vtx1, Vtx* vtx2, Vtx* vtx3,
}
void RaceManager::Load() {
if (WorldContext.GetTrack()) {
if (GetWorld()->GetTrack()) {
mirroredVtxCache.clear();
WorldContext.GetTrack()->Load();
}
}
void RaceManager::UnLoad() {
if (WorldContext.GetTrack()) {
WorldContext.GetTrack()->UnLoad();
GetWorld()->GetTrack()->Load();
} else {
printf("[RaceManager] [Load] Track was nullptr\n");
}
}
@ -97,8 +93,8 @@ void RaceManager::BeginPlay() {
void RaceManager::PostInit() {
// Ruleset options
if (CVarGetInteger("gAllThwompsAreMarty", false) == true) {
for (auto object : gWorldInstance.Objects) {
if (OThwomp* thwomp = dynamic_cast<OThwomp*>(object)) {
for (auto& object : GetWorld()->Objects) {
if (OThwomp* thwomp = dynamic_cast<OThwomp*>(object.get())) {
gObjectList[thwomp->_objectIndex].unk_0D5 = OThwomp::States::JAILED; // Sets all the thwomp behaviour flags to marty
thwomp->Behaviour = OThwomp::States::JAILED;
}
@ -106,8 +102,8 @@ void RaceManager::PostInit() {
}
if (CVarGetInteger("gAllBombKartsChase", false) == true) {
for (auto object : gWorldInstance.Objects) {
if (OBombKart* kart = dynamic_cast<OBombKart*>(object)) {
for (auto& object : GetWorld()->Objects) {
if (OBombKart* kart = dynamic_cast<OBombKart*>(object.get())) {
kart->Behaviour = OBombKart::States::CHASE;
}
}

View File

@ -34,7 +34,6 @@ class RaceManager {
public:
RaceManager(World& world);
virtual void Load(); // virtual required here in the base class to allow inherited classes to override
virtual void UnLoad();
virtual void PreInit();
virtual void BeginPlay();
virtual void PostInit();

View File

@ -0,0 +1,505 @@
#include "SpawnParams.h"
#include "engine/CoreMath.h"
#include "Registry.h"
#include "engine/World.h"
#include "RegisterContent.h"
#include "AllTracks.h"
#include "AllActors.h"
extern "C" {
#include "common_structs.h"
#include "actors.h"
#include "actor_types.h"
#include "assets/textures/other_textures.h"
}
/**
* @file RegisterContent
* This file is responsible for registering the games stock content
*/
/**
*
* DO NOT RE-ORDER ANYTHING IN THIS FILE.
* IT WILL MIX UP THE IDS
*
* Add new content to the end of the function
*/
void RegisterActors(Registry<ActorInfo, const SpawnParams&>& r) {
ActorInfo info;
info = { .ResourceName = "mk:item_box", .Name = "Item Box" };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
spawn_item_box(pos);
});
info = { .ResourceName = "mk:fake_item_box", .Name = "Fake Item Box" };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
spawn_fake_item_box(pos);
});
info = { .ResourceName = "mk:thwomp", .Name = "Thwomp" };
r.Add(info, AddObjectToWorld<OThwomp>);
info = { .ResourceName = "mk:snowman", .Name = "Snowman" };
r.Add(info, AddObjectToWorld<OSnowman>);
info = { .ResourceName = "mk:hot_air_balloon", .Name = "Hot Air Balloon" };
r.Add(info, AddObjectToWorld<OHotAirBalloon>);
info = { .ResourceName = "mk:hedgehog", .Name = "Hedgehog" };
r.Add(info, AddObjectToWorld<OHedgehog>);
info = { .ResourceName = "mk:grand_prix_balloons", .Name = "Grand Prix Balloons" };
r.Add(info, AddObjectToWorld<OGrandPrixBalloons>);
info = { .ResourceName = "mk:flagpole", .Name = "Flagpole", .Tags = { "sign" } };
r.Add(info, AddObjectToWorld<OFlagpole>);
info = { .ResourceName = "mk:crab", .Name = "Crab" };
r.Add(info, AddObjectToWorld<OCrab>);
info = { .ResourceName = "mk:cheep_cheep", .Name = "Cheep Cheep", .Tags = { "passive" } };
r.Add(info, AddObjectToWorld<OCheepCheep>);
info = { .ResourceName = "mk:bomb_kart", .Name = "Bomb Kart", .Tags = { "vehicle" } };
r.Add(info, AddObjectToWorld<OBombKart>);
info = { .ResourceName = "mk:bat", .Name = "Bat" };
r.Add(info, AddObjectToWorld<OBat>);
info = { .ResourceName = "mk:boos", .Name = "Boos" };
r.Add(info, AddObjectToWorld<OBoos>);
info = { .ResourceName = "mk:trophy", .Name = "Trophy" };
r.Add(info, AddObjectToWorld<OTrophy>);
info = { .ResourceName = "mk:trash_bin", .Name = "Trash Bin" };
r.Add(info, AddObjectToWorld<OTrashBin>);
info = { .ResourceName = "mk:seagull", .Name = "Seagull", .Tags = { "passive" } };
r.Add(info, AddObjectToWorld<OSeagull>);
info = { .ResourceName = "mk:chain_chomp", .Name = "Chain Chomp", .Tags = { "vehicle" } };
r.Add(info, AddObjectToWorld<OChainChomp>);
info = { .ResourceName = "mk:podium", .Name = "Podium" };
r.Add(info, AddObjectToWorld<OPodium>);
info = { .ResourceName = "mk:penguin", .Name = "Penguin" };
r.Add(info, AddObjectToWorld<OPenguin>);
info = { .ResourceName = "mk:banana", .Name = "Banana" };
r.Add(info, AddActorToWorld<ABanana>);
info = { .ResourceName = "mk:mario_sign", .Name = "Mario Sign", .Tags = { "sign" } };
r.Add(info, AddActorToWorld<AMarioSign>);
info = { .ResourceName = "mk:wario_sign", .Name = "Wario Sign", .Tags = { "sign" } };
r.Add(info, AddActorToWorld<AWarioSign>);
info = { .ResourceName = "mk:falling_rock", .Name = "Falling Rock", .Tags = { "obstacle" } };
r.Add(info, AddActorToWorld<AFallingRock>);
info = { .ResourceName = "mk:yoshi_egg", .Name = "Yoshi Egg", .Tags = { "obstacle" } };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_YOSHI_EGG);
});
info = { .ResourceName = "mk:piranha_plant", .Name = "Piranha Plant", .Tags = { "foliage", "obstacle" } };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_PIRANHA_PLANT);
});
info = { .ResourceName = "mk:tree_mario_raceway", .Name = "Tree (Mario Raceway)", .Tags = { "foliage" } };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_TREE_MARIO_RACEWAY);
});
info = { .ResourceName = "mk:tree_yoshi_valley", .Name = "Tree (Yoshi Valley)", .Tags = { "foliage" } };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_TREE_YOSHI_VALLEY);
});
info = { .ResourceName = "mk:tree_royal_raceway", .Name = "Tree (Royal Raceway)", .Tags = { "foliage" } };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_TREE_ROYAL_RACEWAY);
});
info = { .ResourceName = "mk:tree_moo_moo_farm", .Name = "Tree (Moo Moo Farm)", .Tags = { "foliage" } };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_TREE_MOO_MOO_FARM);
});
info = { .ResourceName = "mk:palm_tree", .Name = "Palm Tree", .Tags = { "foliage" } };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_PALM_TREE);
});
info = { .ResourceName = "mk:tree_luigi_raceway", .Name = "Tree (Luigi Raceway)", .Tags = { "foliage" } };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_TREE_LUIGI_RACEWAY);
});
info = { .ResourceName = "mk:unknown_0x1b", .Name = "Unknown Plant (0x1B)", .Tags = { "foliage" } };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_UNKNOWN_0x1B);
});
info = { .ResourceName = "mk:tree_peach_castle", .Name = "Tree (Peach Castle)", .Tags = { "foliage" } };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_TREE_PEACH_CASTLE);
});
info = { .ResourceName = "mk:tree_frappe_snowland", .Name = "Tree (Frappe Snowland)", .Tags = { "foliage" } };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_TREE_FRAPPE_SNOWLAND);
});
info = { .ResourceName = "mk:cactus1_kalamari_desert",
.Name = "Cactus 1 (Kalamari Desert)",
.Tags = { "foliage" } };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_CACTUS1_KALAMARI_DESERT);
});
info = { .ResourceName = "mk:cactus2_kalamari_desert",
.Name = "Cactus 2 (Kalamari Desert)",
.Tags = { "foliage" } };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_CACTUS2_KALAMARI_DESERT);
});
info = { .ResourceName = "mk:cactus3_kalamari_desert",
.Name = "Cactus 3 (Kalamari Desert)",
.Tags = { "foliage" } };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_CACTUS3_KALAMARI_DESERT);
});
info = { .ResourceName = "mk:bush_bowsers_castle", .Name = "Bush (Bowser's Castle)" };
r.Add(info, [](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{ 0, 0, 0 });
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = { 0, 0, 0 };
Vec3f vel = { 0, 0, 0 };
add_actor_to_empty_slot(pos, rot, vel, ACTOR_BUSH_BOWSERS_CASTLE);
});
info = { .ResourceName = "mk:finishline", .Name = "Finishline" };
r.Add(info, AddActorToWorld<AFinishline>);
info = { .ResourceName = "mk:train", .Name = "Train", .Tags = { "vehicle" } };
r.Add(info, AddActorToWorld<ATrain>);
info = { .ResourceName = "mk:paddle_boat", .Name = "Paddle Boat", .Tags = { "vehicle" } };
r.Add(info, AddActorToWorld<ABoat>);
info = { .ResourceName = "mk:car", .Name = "Car", .Tags = { "vehicle" } };
r.Add(info, AddActorToWorld<ACar>);
info = { .ResourceName = "mk:truck", .Name = "Truck", .Tags = { "vehicle" } };
r.Add(info, AddActorToWorld<ATankerTruck>);
info = { .ResourceName = "mk:tanker_truck", .Name = "Tanker Truck", .Tags = { "vehicle" } };
r.Add(info, AddActorToWorld<ATankerTruck>);
info = { .ResourceName = "mk:bus", .Name = "Bus", .Tags = { "vehicle" } };
r.Add(info, AddActorToWorld<ATankerTruck>);
info = { .ResourceName = "hm:spaghetti_ship", .Name = "Spaghetti Ship" };
r.Add(info, AddActorToWorld<ASpaghettiShip>);
info = { .ResourceName = "hm:ship", .Name = "Ghostship (HM64)" };
r.Add(info, AddActorToWorld<AShip>);
info = { .ResourceName = "hm:starship", .Name = "Starship (HM64)" };
r.Add(info, AddActorToWorld<AStarship>);
info = { .ResourceName = "hm:cloud", .Name = "Cloud (HM64)", .Tags = { "item" } };
r.Add(info, AddActorToWorld<ACloud>);
info = { .ResourceName = "hm:text", .Name = "Text (HM64)" };
r.Add(info, AddActorToWorld<AText>);
info = { .ResourceName = "mk:bowser_statue", .Name = "Bowser Statue" };
r.Add(info, AddActorToWorld<ABowserStatue>);
}
void RegisterTracks(Registry<TrackInfo>& r) {
TrackInfo info;
info = {
.ResourceName = "mk:mario_raceway",
.Name = "mario raceway",
.DebugName = "m circuit",
.Length = "567m",
.MinimapTexture = minimap_mario_raceway,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<MarioRaceway>()); });
info = {
.ResourceName = "mk:choco_mountain",
.Name = "choco mountain",
.DebugName = "mountain",
.Length = "687m",
.MinimapTexture = minimap_choco_mountain,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<ChocoMountain>()); });
info = {
.ResourceName = "mk:bowsers_castle",
.Name = "bowser's castle",
.DebugName = "castle",
.Length = "777m",
.MinimapTexture = minimap_bowsers_castle,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<BowsersCastle>()); });
info = {
.ResourceName = "mk:banshee_boardwalk",
.Name = "banshee boardwalk",
.DebugName = "ghost",
.Length = "747m",
.MinimapTexture = minimap_banshee_boardwalk,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<BansheeBoardwalk>()); });
info = {
.ResourceName = "mk:yoshi_valley",
.Name = "yoshi valley",
.DebugName = "maze",
.Length = "772m",
.MinimapTexture = minimap_yoshi_valley,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<YoshiValley>()); });
info = {
.ResourceName = "mk:frappe_snowland",
.Name = "frappe snowland",
.DebugName = "snow",
.Length = "734m",
.MinimapTexture = minimap_frappe_snowland,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<FrappeSnowland>()); });
info = {
.ResourceName = "mk:koopa_beach",
.Name = "koopa troopa beach",
.DebugName = "beach",
.Length = "691m",
.MinimapTexture = minimap_koopa_troopa_beach,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<KoopaTroopaBeach>()); });
info = {
.ResourceName = "mk:royal_raceway",
.Name = "royal raceway",
.DebugName = "p circuit",
.Length = "1025m",
.MinimapTexture = minimap_royal_raceway,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<RoyalRaceway>()); });
info = {
.ResourceName = "mk:luigi_raceway",
.Name = "luigi raceway",
.DebugName = "l circuit",
.Length = "717m",
.MinimapTexture = minimap_luigi_raceway,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<LuigiRaceway>()); });
info = {
.ResourceName = "mk:moo_moo_farm",
.Name = "moo moo farm",
.DebugName = "farm",
.Length = "527m",
.MinimapTexture = minimap_moo_moo_farm,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<MooMooFarm>()); });
info = {
.ResourceName = "mk:toads_turnpike",
.Name = "toad's turnpike",
.DebugName = "highway",
.Length = "1036m",
.MinimapTexture = minimap_toads_turnpike,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<ToadsTurnpike>()); });
info = {
.ResourceName = "mk:kalimari_desert",
.Name = "kalimari desert",
.DebugName = "desert",
.Length = "753m",
.MinimapTexture = minimap_kalimari_desert,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<KalimariDesert>()); });
info = {
.ResourceName = "mk:sherbet_land",
.Name = "sherbet land",
.DebugName = "sherbet",
.Length = "756m",
.MinimapTexture = minimap_sherbet_land,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<SherbetLand>()); });
info = {
.ResourceName = "mk:rainbow_road",
.Name = "rainbow road",
.DebugName = "rainbow",
.Length = "2000m",
.MinimapTexture = minimap_rainbow_road,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<RainbowRoad>()); });
info = {
.ResourceName = "mk:wario_stadium",
.Name = "wario stadium",
.DebugName = "stadium",
.Length = "1591m",
.MinimapTexture = minimap_wario_stadium,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<WarioStadium>()); });
info = {
.ResourceName = "mk:block_fort",
.Name = "block fort",
.DebugName = "block",
.Length = "",
.MinimapTexture = minimap_block_fort,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<BlockFort>()); });
info = {
.ResourceName = "mk:skyscraper",
.Name = "skyscraper",
.DebugName = "skyscraper",
.Length = "",
.MinimapTexture = minimap_skyscraper,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<Skyscraper>()); });
info = {
.ResourceName = "mk:double_deck",
.Name = "double deck",
.DebugName = "deck",
.Length = "",
.MinimapTexture = minimap_double_deck,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<DoubleDeck>()); });
info = {
.ResourceName = "mk:dk_jungle",
.Name = "d.k.'s jungle parkway",
.DebugName = "jungle",
.Length = "893m",
.MinimapTexture = minimap_dks_jungle_parkway,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<DKJungle>()); });
info = {
.ResourceName = "mk:big_donut",
.Name = "big donut",
.DebugName = "doughnut",
.Length = "",
.MinimapTexture = minimap_big_donut,
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<BigDonut>()); });
info = {
.ResourceName = "mk:test_track",
.Name = "test track",
.DebugName = "test track",
.Length = "100m",
};
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<TestTrack>()); });
}

View File

@ -0,0 +1,18 @@
#pragma once
#include "Object.h"
#include "Registry.h"
#include "SpawnParams.h"
#include "port/Game.h"
#include <memory>
template<class T> static OObject* AddObjectToWorld(const SpawnParams& params) {
return GetWorld()->AddObject(std::make_unique<T>(params));
}
template<class T> static AActor* AddActorToWorld(const SpawnParams& params) {
return GetWorld()->AddActor(std::make_unique<T>(params));
}
void RegisterActors(Registry<ActorInfo, const SpawnParams&>& r);
void RegisterTracks(Registry<TrackInfo>& r);

View File

@ -1,372 +0,0 @@
#include "SpawnParams.h"
#include "engine/CoreMath.h"
#include "Registry.h"
#include "engine/World.h"
#include "AllActors.h"
extern "C" {
#include "common_structs.h"
#include "actors.h"
#include "actor_types.h"
}
void RegisterGameActors() {
RegisterActor("mk:item_box",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
spawn_item_box(pos);
}
);
RegisterActor("mk:fake_item_box",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
spawn_fake_item_box(pos);
}
);
RegisterActor("mk:thwomp",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OThwomp(params));
}
);
RegisterActor("mk:snowman",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OSnowman(params));
}
);
RegisterActor("mk:hot_air_balloon",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OHotAirBalloon(params));
}
);
RegisterActor("mk:hedgehog",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OHedgehog(params));
}
);
RegisterActor("mk:grand_prix_balloons",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OGrandPrixBalloons(params));
}
);
RegisterActor("mk:flagpole",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OFlagpole(params));
}
);
RegisterActor("mk:crab",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OCrab(params));
}
);
RegisterActor("mk:cheep_cheep",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OCheepCheep(params));
}
);
RegisterActor("mk:bomb_kart",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OBombKart(params));
}
);
RegisterActor("mk:bat",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OBat(params));
}
);
RegisterActor("mk:boos",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OBoos(params));
}
);
RegisterActor("mk:trophy",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OTrophy(params));
}
);
RegisterActor("mk:trash_bin",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OTrashBin(params));
}
);
RegisterActor("mk:seagull",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OSeagull(params));
}
);
RegisterActor("mk:chain_chomp",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OChainChomp());
}
);
RegisterActor("mk:podium",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OPodium(params));
}
);
RegisterActor("mk:penguin",
[](const SpawnParams& params) {
gWorldInstance.AddObject(new OPenguin(params));
}
);
RegisterActor("mk:banana",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new ABanana(params));
}
);
RegisterActor("mk:mario_sign",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new AMarioSign(params));
}
);
RegisterActor("mk:wario_sign",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new AWarioSign(params));
}
);
RegisterActor("mk:falling_rock",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new AFallingRock(params));
}
);
RegisterActor("mk:yoshi_egg",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_YOSHI_EGG);
}
);
RegisterActor("mk:piranha_plant",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_PIRANHA_PLANT);
}
);
RegisterActor("mk:tree_mario_raceway",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_TREE_MARIO_RACEWAY);
}
);
RegisterActor("mk:tree_yoshi_valley",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_TREE_YOSHI_VALLEY);
}
);
RegisterActor("mk:tree_royal_raceway",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_TREE_ROYAL_RACEWAY);
}
);
RegisterActor("mk:tree_moo_moo_farm",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_TREE_MOO_MOO_FARM);
}
);
RegisterActor("mk:palm_tree",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_PALM_TREE);
}
);
RegisterActor("mk:unknown_0x1a",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_TREE_LUIGI_RACEWAY);
}
);
RegisterActor("mk:unknown_0x1b",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_UNKNOWN_0x1B);
}
);
RegisterActor("mk:tree_peach_castle",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_TREE_PEACH_CASTLE);
}
);
RegisterActor("mk:tree_frappe_snowland",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_TREE_FRAPPE_SNOWLAND);
}
);
RegisterActor("mk:cactus1_kalamari_desert",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_CACTUS1_KALAMARI_DESERT);
}
);
RegisterActor("mk:cactus2_kalamari_desert",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_CACTUS2_KALAMARI_DESERT);
}
);
RegisterActor("mk:cactus3_kalamari_desert",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_CACTUS3_KALAMARI_DESERT);
}
);
RegisterActor("mk:bush_bowsers_castle",
[](const SpawnParams& params) {
FVector loc = params.Location.value_or(FVector{0, 0, 0});
Vec3f pos = { loc.x, loc.y, loc.z };
Vec3s rot = {0, 0, 0};
Vec3f vel = {0, 0, 0};
add_actor_to_empty_slot(pos, rot, vel, ACTOR_BUSH_BOWSERS_CASTLE);
}
);
RegisterActor("mk:train",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new ATrain(params));
}
);
RegisterActor("mk:paddle_boat",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new ABoat(params));
}
);
RegisterActor("mk:car",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new ACar(params));
}
);
RegisterActor("mk:truck",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new ATankerTruck(params));
}
);
RegisterActor("mk:tanker_truck",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new ATankerTruck(params));
}
);
RegisterActor("mk:bus",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new ATankerTruck(params));
}
);
RegisterActor("hm:spaghetti_ship",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new ASpaghettiShip(params));
}
);
RegisterActor("hm:ship",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new AShip(params));
}
);
RegisterActor("hm:starship",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new AStarship(params));
}
);
RegisterActor("hm:cloud",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new ACloud(params));
}
);
RegisterActor("hm:text",
[](const SpawnParams& params) {
gWorldInstance.AddActor(new AText(params));
}
);
}

View File

@ -1,3 +0,0 @@
#pragma once
void RegisterGameActors();

View File

@ -1,32 +0,0 @@
#include <functional>
#include <unordered_map>
#include <string>
#include "Registry.h"
#include "engine/CoreMath.h"
extern "C" {
#include "actors.h"
#include "actor_types.h"
}
std::unordered_map<std::string, ActorRegistryEntry> gActorRegistry;
void RegisterActor(const std::string& name,
std::function<void(const SpawnParams&)> spawnFunc)
{
gActorRegistry[name] = { spawnFunc };
}
void Registry_SpawnActor(SpawnParams& params) {
auto it = gActorRegistry.find(params.Name);
if (it != gActorRegistry.end() && it->second.spawnFunc) {
printf("[Registry] Spawned %s\n", params.Name.c_str());
it->second.spawnFunc(params);
}
}
// @arg name Must be a resource name such as mk:car
bool Registry_Find(const std::string& name) {
return gActorRegistry.find(name) != gActorRegistry.end();
}

View File

@ -1,14 +1,114 @@
#pragma once
#include <libultraship.h>
#include "SpawnParams.h"
#include <string>
#include <unordered_map>
#include <functional>
#include <set>
struct ActorRegistryEntry {
std::function<void(const SpawnParams&)> spawnFunc;
struct TrackInfo {
int32_t Id;
std::string Path; // Path to the custom track
std::string ResourceName;
std::string Name;
std::string DebugName;
std::string Length;
const char* MinimapTexture;
// std::string PreviewTexture;
};
extern std::unordered_map<std::string, ActorRegistryEntry> gActorRegistry;
struct ActorInfo {
int32_t Id;
std::string ResourceName;
std::string Name;
std::set<std::string> Tags; // Category for filtering
};
void Registry_SpawnActor(SpawnParams& params);
void RegisterActor(const std::string& name,
std::function<void(const SpawnParams&)> spawnFunc);
/**
* TInfo must have a ResourceName member of type std::string
* This should be a unique string such as hm:cloud or hm:harbour
* user_name:my_mod
*
* TArgs the parameters passed into the callback function
*
* Example Usage:
*
* Registry<ActorInfo> gActorRegistry;
*
* ActorInfo actorInfo {
* .ResourceName = "hm:cloud",
* };
* SpawnParams params;
* params.Location = FVector(0, 0, 0);
*
* gActorRegistry.Add(actorInfo, [](params) {
* GetWorld()->AddActor(new ACloud(params));
* });
*
* gActorRegistry.Invoke("hm:cloud", params);
*
*/
template<typename TInfo, typename... TArgs>
// ^ Scary template key word
class Registry {
public:
/**
* Callback explanation
*
* This is just a lambda function.
*
* Usage: gRegistry.Add("hm:harbour", [](parameters) { // My code here })
*/
using Callback = std::function<void(TArgs...)>;
void Add(TInfo& info, Callback func) {
info.Id = mCounter++;
// Needs to allow overwriting to support mod hot-reloading
mMap[info.ResourceName] = Entry{info, std::move(func)};
}
const TInfo* GetInfo(const std::string& resourceName) const {
auto it = mMap.find(resourceName);
return (it != mMap.end()) ? &it->second.Info : nullptr;
}
void Invoke(const std::string& resourceName, TArgs... args) {
auto it = mMap.find(resourceName);
if (it != mMap.end() && it->second.Func) {
// Using C++ variadic template expansion to call the function
printf("[Registry] Invoking %s\n", resourceName.c_str());
it->second.Func(std::forward<TArgs>(args)...);
} else {
printf("[Registry] Error: %s not found or function is null.\n", resourceName.c_str());
}
}
bool Find(const std::string& resourceName) const {
return mMap.find(resourceName) != mMap.end();
}
std::vector<const TInfo*> GetAllInfo() const {
std::vector<const TInfo*> list;
list.reserve(mMap.size());
for (auto& pair : mMap) {
list.push_back(&pair.second.Info);
}
return list;
}
void Clear() {
mMap.clear();
mCounter = 0;
}
private:
int32_t mCounter;
struct Entry {
TInfo Info;
Callback Func;
};
// key: str, value: lambda function
std::unordered_map<std::string, Registry::Entry> mMap;
};

View File

@ -1,75 +0,0 @@
#include "Rulesets.h"
#include "objects/Thwomp.h"
#include "objects/Trophy.h"
#include "objects/BombKart.h"
#include "actors/Text.h"
extern "C" {
#include "code_800029B0.h"
#include "memory.h"
}
// Before the game is loaded, and before vertices and displaylists are unpacked.
// Only runs a single time at the beginning of a track.
void Rulesets::PreLoad() {
}
// Just before BeginPlay() (used to spawn actors) is ran.
// Only runs a single time at the beginning of a track.
void Rulesets::PreInit() {
if (CVarGetInteger("gDisableItemboxes", false) == true) {
gPlaceItemBoxes = false;
} else {
gPlaceItemBoxes = true;
}
}
// Just after BeginPlay() is ran.
// Only runs a single time at the beginning of a track.
void Rulesets::PostInit() {
if (CVarGetInteger("gAllThwompsAreMarty", false) == true) {
for (auto object : gWorldInstance.Objects) {
if (OThwomp* thwomp = dynamic_cast<OThwomp*>(object)) {
gObjectList[thwomp->_objectIndex].unk_0D5 = OThwomp::States::JAILED; // Sets all the thwomp behaviour flags to marty
thwomp->Behaviour = OThwomp::States::JAILED;
}
}
}
if (CVarGetInteger("gAllBombKartsChase", false) == true) {
for (auto object : gWorldInstance.Objects) {
if (OBombKart* kart = dynamic_cast<OBombKart*>(object)) {
kart->Behaviour = OBombKart::States::CHASE;
}
}
}
if (CVarGetInteger("gGoFish", false) == true) {
OTrophy::Spawn(FVector(0,0,0), OTrophy::TrophyType::GOLD, OTrophy::Behaviour::GO_FISH);
}
if (CVarGetInteger("gPlayerNames", false) == true) {
std::string playerNames[NUM_PLAYERS] = {
"Player 1", "Player 2", "Player 3",
"Player 4", "Player 5", "Player 6",
"Player 7", "Player 8"
};
for (size_t i = 0; i < NUM_PLAYERS; i++) {
// text, pos, scale, mode, playerIndex
AText* text = AText::Spawn(playerNames[i], FVector(0, 0, 0), FVector(0.15f, 0.15f, 0.15f), AText::TextMode::FOLLOW_PLAYER, i);
text->ScaleX = 1.0f;
text->Scale.x = 0.15f;
text->Scale.y = 0.15f;
text->Scale.z = 0.15f;
text->Animate = false; // Cycle between colours similar to grand prix title text
// White
for (size_t j = 0; j < 4; j++) {
text->TextColour[j] = {255, 255, 255, 255};
}
}
}
}

View File

@ -1,11 +0,0 @@
#pragma once
#include <libultraship.h>
#include "World.h"
class Rulesets {
public:
virtual void PreLoad();
virtual void PreInit();
virtual void PostInit();
};

View File

@ -24,8 +24,8 @@ void TrainSmokeTick() {
s32 temp_a0;
Object* object;
for (auto& actor : gWorldInstance.Actors) {
if (auto train = dynamic_cast<ATrain*>(actor)) {
for (auto& actor : GetWorld()->Actors) {
if (auto* train = dynamic_cast<ATrain*>(actor.get())) {
if (train->SmokeTimer != 0) {
train->SmokeTimer -= 1;
}
@ -49,7 +49,7 @@ void TrainSmokeTick() {
train->SmokeTimer = 100;
}
}
} else if (auto boat = dynamic_cast<ABoat*>(actor)) {
} else if (auto* boat = dynamic_cast<ABoat*>(actor.get())) {
if (boat->SmokeTimer != 0) {
boat->SmokeTimer -= 1;
}
@ -79,8 +79,8 @@ void TrainSmokeTick() {
void TrainSmokeDraw(s32 cameraId) {
Camera* camera = &camera1[cameraId];
for (auto& actor : gWorldInstance.Actors) {
if (auto train = dynamic_cast<ATrain*>(actor)) {
for (auto& actor : GetWorld()->Actors) {
if (auto train = dynamic_cast<ATrain*>(actor.get())) {
gSPDisplayList(gDisplayListHead++, (Gfx*) D_0D007AE0);
load_texture_block_i8_nomirror((uint8_t*) D_0D029458, 32, 32);
func_8004B72C(255, 255, 255, 255, 255, 255, 255);
@ -94,7 +94,7 @@ void TrainSmokeDraw(s32 cameraId) {
FrameInterpolation_RecordCloseChild();
}
}
} else if (auto boat = dynamic_cast<ABoat*>(actor)) {
} else if (auto* boat = dynamic_cast<ABoat*>(actor.get())) {
gSPDisplayList(gDisplayListHead++, (Gfx*) D_0D007AE0);
load_texture_block_i8_nomirror((uint8_t*) D_0D029458, 32, 32);

118
src/engine/TrackBrowser.cpp Normal file
View File

@ -0,0 +1,118 @@
#include "TrackBrowser.h"
#include "port/Engine.h"
#include "engine/editor/SceneManager.h"
TrackBrowser* TrackBrowser::Instance;
void TrackBrowser::FindCustomTracks() {
auto manager = GameEngine::Instance->context->GetResourceManager()->GetArchiveManager();
auto ptr2 = manager->ListDirectories("tracks/*");
if (ptr2) {
auto dirs = *ptr2;
for (const std::string& dir : dirs) {
std::string name = dir.substr(dir.find_last_of('/') + 1);
std::string sceneFile = dir + "/scene.json";
std::string minimapFile = dir + "/minimap.png";
// The track has a valid scene file, add it to the registry
if (manager->HasFile(sceneFile)) {
auto archive = manager->GetArchiveFromFile(sceneFile);
TrackInfo info;
info.Path = dir;
Editor::LoadTrackInfo(info, archive, sceneFile);
printf("Added custom track %s\n", info.Name.c_str());
gTrackRegistry.Add(info, [info, archive]() {
auto track = std::make_unique<Track>();
track->ResourceName = info.ResourceName;
track->Archive = archive;
GetWorld()->SetCurrentTrack(std::move(track));
});
} else { // The track does not have a valid scene file
const std::string file = dir + "/data_track_sections";
// If the track has a data_track_sections file,
// then it must at least be a valid track.
// So lets add it as an uninitialized track.
if (manager->HasFile(file)) {
TrackInfo info;
std::string resName = std::string("mods:") + name;
info.ResourceName = resName;
info.Name = name;
info.DebugName = name;
auto archive = manager->GetArchiveFromFile(file);
//mNewTracks.push_back({info, "", dir, archive});
auto track = std::make_unique<Track>();
Editor::SaveLevel(track.get()); // Write scene file so it will show up in the track browser
gTrackRegistry.Add(info, [info, archive]() {
auto track = std::make_unique<Track>();
track->ResourceName = info.ResourceName;
track->Archive = archive;
GetWorld()->SetCurrentTrack(std::move(track));
});
} else {
printf("ContentBrowser.cpp: Track '%s' missing required track files. Cannot add to game\n Missing %s/data_track_sections file\n", name.c_str(), dir.c_str());
}
}
}
}
}
extern "C" void TrackBrowser_SetTrack(const char* name) {
TrackBrowser::Instance->SetTrack(std::string(name));
}
extern "C" void TrackBrowser_SetTrackFromCup() {
TrackBrowser::Instance->SetTrack(GetWorld()->GetCurrentCup()->GetTrack());
}
extern "C" void TrackBrowser_NextTrack(void) {
TrackBrowser::Instance->NextTrack();
}
extern "C" void TrackBrowser_PreviousTrack(void) {
TrackBrowser::Instance->PreviousTrack();
}
extern "C" size_t TrackBrowser_GetTrackIndex(void) {
return TrackBrowser::Instance->GetTrackIndex();
}
extern "C" const char* TrackBrowser_GetTrackName(void) {
return TrackBrowser::Instance->GetTrackName();
}
extern "C" const char* TrackBrowser_GetTrackDebugName(void) {
return TrackBrowser::Instance->GetTrackDebugName();
}
extern "C" const char* TrackBrowser_GetTrackLength(void) {
return TrackBrowser::Instance->GetTrackLength();
}
extern "C" void TrackBrowser_SetTrackByIdx(size_t trackIndex) {
TrackBrowser::Instance->SetTrackByIdx(trackIndex);
}
extern "C" const char* TrackBrowser_GetTrackNameByIdx(size_t trackIndex) {
return TrackBrowser::Instance->GetTrackNameByIdx(trackIndex);
}
extern "C" const char* TrackBrowser_GetTrackDebugNameByIdx(size_t trackIndex) {
return TrackBrowser::Instance->GetTrackDebugNameByIdx(trackIndex);
}
extern "C" const char* TrackBrowser_GetTrackLengthByIdx(size_t trackIndex) {
return TrackBrowser::Instance->GetTrackLengthByIdx(trackIndex);
}
extern "C" const char* TrackBrowser_GetMinimapTextureByIdx(size_t trackIndex) {
return TrackBrowser::Instance->GetMinimapTextureByIdx(trackIndex);
}

192
src/engine/TrackBrowser.h Normal file
View File

@ -0,0 +1,192 @@
#ifndef TRACKBROWSER_H
#define TRACKBROWSER_H
#include <libultraship.h>
#include "port/Game.h"
#ifdef __cplusplus
#include <vector>
/**
* Allows exploring tracks in the menus
*/
class TrackBrowser {
private:
// Holds all available tracks
std::vector<const TrackInfo*> mTracks;
size_t mTrackIndex = 0;
public:
static TrackBrowser* Instance;
TrackBrowser(const Registry<TrackInfo>& registry) {
mTracks = registry.GetAllInfo();
std::sort(mTracks.begin(), mTracks.end(), [](const TrackInfo* a, const TrackInfo* b) {
return a->Id < b->Id;
});
Instance = this;
}
void FindCustomTracks();
void Refresh(const Registry<TrackInfo>& registry) {
mTracks.clear();
mTracks = registry.GetAllInfo();
std::sort(mTracks.begin(), mTracks.end(), [](const TrackInfo* a, const TrackInfo* b) {
return a->Id < b->Id;
});
mTrackIndex = 0;
}
void Reset() {
mTrackIndex = 0;
}
void SetTrack(std::string name) {
if (gTrackRegistry.Find(name)) {
gTrackRegistry.Invoke(name);
} else {
throw std::runtime_error("[World] [SetTrack()] Track name not found in Track list: " + name);
}
}
void NextTrack() {
if (mTracks.empty()) return;
mTrackIndex = (mTrackIndex + 1) % mTracks.size();
gTrackRegistry.Invoke(mTracks[mTrackIndex]->ResourceName);
}
void PreviousTrack() {
if (mTracks.empty()) return;
mTrackIndex = (mTrackIndex + mTracks.size() - 1) % mTracks.size();
gTrackRegistry.Invoke(mTracks[mTrackIndex]->ResourceName);
}
size_t GetTrackIndex() {
return mTrackIndex;
}
const char* GetTrackName() {
if (mTracks.empty()) return "";
if (mTracks[mTrackIndex]) {
return mTracks[mTrackIndex]->Name.c_str();
}
return "";
}
const char* GetTrackDebugName() {
if (mTracks.empty()) return "";
if (mTracks[mTrackIndex]) {
return mTracks[mTrackIndex]->DebugName.c_str();
}
return "";
}
const char* GetTrackLength() {
if (mTracks.empty()) return "";
if (mTracks[mTrackIndex]) {
return mTracks[mTrackIndex]->Length.c_str();
}
return "";
}
/**
* The index setters and getters here are for legacy code support
* Try not to rely too heavily on these functions especially for custom content.
*
* The content at an index may not be guaranteed if other clients have different custom content.
* Even the same content could be loaded at a different index
*
* The location of stock content *should* be consistent across all clients.
*/
void SetTrackByIdx(size_t trackIndex) {
if (trackIndex >= mTracks.size()) {
printf("[TrackBrowser] [SetTrackById] Error: trackIndex %zu out of bounds (max %zu)\n", trackIndex, mTracks.size());
return;
}
if (nullptr == mTracks[mTrackIndex]) {
printf("[TrackBrowser] [SetTrackById] Error: TrackInfo at index %zu is null\n", mTrackIndex);
return;
}
mTrackIndex = trackIndex;
gTrackRegistry.Invoke(mTracks[mTrackIndex]->ResourceName);
}
const char* GetTrackNameByIdx(size_t trackIndex) {
if (trackIndex >= mTracks.size()) {
printf("[TrackBrowser] [GetTrackNameByIdx] Error: trackIndex %zu out of bounds (max %zu)\n", trackIndex, mTracks.size());
return "";
}
if (nullptr == mTracks[trackIndex]) {
printf("[TrackBrowser] [GetTrackNameByIdx] Error: TrackInfo at index %zu is null\n", trackIndex);
return "";
}
return mTracks[trackIndex]->Name.c_str();
}
const char* GetTrackDebugNameByIdx(size_t trackIndex) {
if (trackIndex >= mTracks.size()) {
printf("[TrackBrowser] [GetTrackDebugNameByIdx] Error: trackIndex %zu out of bounds (max %zu)\n", trackIndex, mTracks.size());
return "";
}
if (nullptr == mTracks[trackIndex]) {
printf("[TrackBrowser] [GetTrackDebugNameByIdx] Error: TrackInfo at index %zu is null\n", trackIndex);
return "";
}
return mTracks[trackIndex]->DebugName.c_str();
}
const char* GetTrackLengthByIdx(size_t trackIndex) {
if (trackIndex >= mTracks.size()) {
printf("[TrackBrowser] [GetTrackLengthByIdx] Error: trackIndex %zu out of bounds (max %zu)\n", trackIndex, mTracks.size());
return "";
}
if (nullptr == mTracks[trackIndex]) {
printf("[TrackBrowser] [GetTrackLengthByIdx] Error: TrackInfo at index %zu is null\n", trackIndex);
return "";
}
return mTracks[trackIndex]->Length.c_str();
}
const char* GetMinimapTextureByIdx(size_t trackIndex) {
if (trackIndex >= mTracks.size()) {
printf("[TrackBrowser] [GetTrackMinimapTextureByIdx] Error: trackIndex %zu out of bounds (max %zu)\n", trackIndex, mTracks.size());
return NULL;
}
if (nullptr == mTracks[trackIndex]) {
printf("[TrackBrowser] [GetTrackMinimapTextureByIdx] Error: TrackInfo at index %zu is null\n", trackIndex);
return NULL;
}
return mTracks[trackIndex]->MinimapTexture;
}
};
#endif // __cplusplus
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void TrackBrowser_SetTrack(const char* name);
void TrackBrowser_SetTrackFromCup(void); // <-- Not in TrackBrowser class
void TrackBrowser_NextTrack(void);
void TrackBrowser_PreviousTrack(void);
size_t TrackBrowser_GetTrackIndex(void);
const char* TrackBrowser_GetTrackName(void);
const char* TrackBrowser_GetTrackDebugName(void);
const char* TrackBrowser_GetTrackLength(void);
void TrackBrowser_SetTrackByIdx(size_t trackIndex);
const char* TrackBrowser_GetTrackNameByIdx(size_t trackIndex);
const char* TrackBrowser_GetTrackDebugNameByIdx(size_t trackIndex);
const char* TrackBrowser_GetTrackLengthByIdx(size_t trackIndex);
const char* TrackBrowser_GetMinimapTextureByIdx(size_t trackIndex);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // TRACKBROWSER_H

View File

@ -29,9 +29,8 @@ void TrainCrossing::CrossingTrigger() {
s32 i;
OnTriggered = 0;
for (const auto& actor : gWorldInstance.Actors) {
if (auto train = dynamic_cast<ATrain*>(actor)) {
;
for (const auto& actor : GetWorld()->Actors) {
if (auto* train = dynamic_cast<ATrain*>(actor.get())) {
f32 radius = DynamicRadius(train->Locomotive.position, train->Locomotive.velocity, Position);
if (Distance(train->Locomotive.position, Position) < radius) {

View File

@ -2,35 +2,28 @@
#include "World.h"
#include "Cup.h"
#include "tracks/Track.h"
#include "objects/BombKart.h"
#include "TrainCrossing.h"
#include <memory>
#include "objects/Object.h"
#include "port/Game.h"
#include "editor/GameObject.h"
extern "C" {
#include "camera.h"
#include "objects.h"
#include "main.h"
#include "defines.h"
#include "audio/external.h"
#include "menus.h"
#include "code_800029B0.h"
#include "assets/models/common_data.h"
#include "assets/models/tracks/mario_raceway/mario_raceway_data.h"
}
#include "engine/cameras/GameCamera.h"
#include "engine/cameras/FreeCamera.h"
#include "engine/cameras/TourCamera.h"
#include "engine/cameras/LookBehindCamera.h"
std::shared_ptr<Track> mTrack;
World* World::Instance;
std::unique_ptr<Track> mTrack;
Cup* CurrentCup;
World::World() {
Instance = this;
RaceManagerInstance = std::make_unique<RaceManager>(*this);
}
@ -38,29 +31,17 @@ World::~World() {
CleanWorld();
}
std::shared_ptr<Track> World::AddTrack(std::shared_ptr<Track> track) {
gWorldInstance.Tracks.push_back(track);
return track;
}
void World::AddCup(Cup* cup) {
Cups.push_back(cup);
}
void World::SetCurrentTrack(std::shared_ptr<Track> track) {
if (mTrack) {
UnLoadTrack();
}
void World::SetCurrentTrack(std::unique_ptr<Track> track) {
if (mTrack == track) {
return;
}
mTrack = std::move(track);
}
void World::SetTrackFromCup() {
SetCurrentTrack(CurrentCup->GetTrack());
}
TrainCrossing* World::AddCrossing(Vec3f position, u32 waypointMin, u32 waypointMax, f32 approachRadius,
f32 exitRadius) {
auto crossing = std::make_shared<TrainCrossing>(position, waypointMin, waypointMax, approachRadius, exitRadius);
@ -114,35 +95,6 @@ void World::SetCurrentCup(Cup* cup) {
}
}
void World::SetTrack(const char* name) {
//! @todo Use content dictionary instead
for (size_t i = 0; i < Tracks.size(); i++) {
if (strcmp(Tracks[i]->Props.Name, name) == 0) {
SetCurrentTrack(Tracks[i]);
break;
}
}
std::runtime_error("[World] [SetTrack()] Track name not found in Track list");
}
void World::NextTrack() {
if (TrackIndex < Tracks.size() - 1) {
TrackIndex++;
} else {
TrackIndex = 0;
}
gWorldInstance.SetCurrentTrack(Tracks[TrackIndex]);
}
void World::PreviousTrack() {
if (TrackIndex > 0) {
TrackIndex--;
} else {
TrackIndex = Tracks.size() - 1;
}
gWorldInstance.SetCurrentTrack(Tracks[TrackIndex]);
}
void World::TickCameras() {
for (size_t i = 0; i < 4; i++) {
@ -161,19 +113,19 @@ void World::TickCameras() {
}
}
AActor* World::AddActor(AActor* actor) {
Actors.push_back(actor);
actor->BeginPlay();
return Actors.back();
AActor* World::AddActor(std::unique_ptr<AActor> actor) {
Actors.push_back(std::move(actor));
Actors.back()->BeginPlay();
return Actors.back().get();
}
struct Actor* World::AddBaseActor() {
Actors.push_back(new AActor());
Actors.push_back(std::make_unique<AActor>());
AActor* actor = Actors.back();
AActor* actor = Actors.back().get();
// Skip C++ vtable to access variables in C
return reinterpret_cast<struct Actor*>(reinterpret_cast<char*>(Actors.back()) + sizeof(void*));
return reinterpret_cast<struct Actor*>(reinterpret_cast<char*>(actor) + sizeof(void*));
}
void World::ActorBeginPlay(Actor* actor) {
@ -201,21 +153,21 @@ Actor* World::ConvertAActorToActor(AActor* actor) {
}
AActor* World::GetActor(size_t index) {
return Actors[index];
return Actors[index].get();
}
void World::TickActors() {
// This only ticks modded actors
for (AActor* actor : Actors) {
for (auto& actor : Actors) {
if (actor->IsMod()) {
actor->Tick();
}
}
}
StaticMeshActor* World::AddStaticMeshActor(std::string name, FVector pos, IRotator rot, FVector scale, std::string model, int32_t* collision) {
StaticMeshActors.push_back(new StaticMeshActor(name, pos, rot, scale, model, collision));
auto actor = StaticMeshActors.back();
StaticMeshActor* World::AddStaticMeshActor(const std::string& name, FVector pos, IRotator rot, FVector scale, const std::string& model, int32_t* collision) {
StaticMeshActors.push_back(std::make_unique<StaticMeshActor>(name, pos, rot, scale, model, collision));
auto* actor = StaticMeshActors.back().get();
return actor;
}
@ -225,8 +177,20 @@ void World::DrawStaticMeshActors() {
}
}
OObject* World::AddObject(OObject* object) {
Objects.push_back(object);
// OObject* World::AddObject(OObject object) {
// Objects.push_back(std::make_unique<OObject>(object));
// // This is an example of how to get the C object.
// // However, nothing is being done with it, so it's been commented out.
// // if (object->_objectIndex != -1) {
// // Object* cObj = &gObjectList[object->_objectIndex];
// // }
// return Objects.back().get();
// }
OObject* World::AddObject(std::unique_ptr<OObject> object) {
Objects.push_back(std::move(object));
// This is an example of how to get the C object.
// However, nothing is being done with it, so it's been commented out.
@ -234,11 +198,11 @@ OObject* World::AddObject(OObject* object) {
// Object* cObj = &gObjectList[object->_objectIndex];
// }
return Objects.back();
return Objects.back().get();
}
void World::TickObjects() {
for (const auto& object : Objects) {
for (auto& object : Objects) {
object->Tick();
}
}
@ -246,7 +210,7 @@ void World::TickObjects() {
// Some objects such as lakitu are ticked in process_game_tick.
// This is a fallback to support those objects. Probably don't use this.
void World::TickObjects60fps() {
for (const auto& object : Objects) {
for (auto& object : Objects) {
object->Tick60fps();
}
}
@ -257,7 +221,7 @@ ParticleEmitter* World::AddEmitter(ParticleEmitter* emitter) {
}
void World::DrawObjects(s32 cameraId) {
for (const auto& object : Objects) {
for (auto& object : Objects) {
object->Draw(cameraId);
}
}
@ -276,7 +240,7 @@ void World::DrawParticles(s32 cameraId) {
// Sets OObjects or AActors static member variables back to default values
void World::Reset() {
for (const auto& object : Objects) {
for (auto& object : Objects) {
object->Reset(); // Used for OPenguin
}
}
@ -292,33 +256,22 @@ Object* World::GetObjectByIndex(size_t index) {
// Deletes all objects from the world
void World::CleanWorld(void) {
printf("[Game.cpp] Clean World\n");
World* world = &gWorldInstance;
for (auto& actor : world->Actors) {
delete actor;
}
gWorldInstance.Reset(); // Reset OObjects
for (auto& object : world->Objects) {
delete object;
}
World::Reset(); // Reset OObjects
for (auto& emitter : world->Emitters) {
for (auto& emitter : Emitters) {
delete emitter;
}
for (auto& actor : world->StaticMeshActors) {
delete actor;
}
for (size_t i = 0; i < ARRAY_COUNT(gWorldInstance.playerBombKart); i++) {
gWorldInstance.playerBombKart[i].state = PlayerBombKart::PlayerBombKartState::DISABLED;
gWorldInstance.playerBombKart[i]._primAlpha = 0;
for (size_t i = 0; i < ARRAY_COUNT(mPlayerBombKart); i++) {
mPlayerBombKart[i].state = PlayerBombKart::PlayerBombKartState::DISABLED;
mPlayerBombKart[i]._primAlpha = 0;
}
gEditor.ClearObjects();
gWorldInstance.Actors.clear();
gWorldInstance.StaticMeshActors.clear();
gWorldInstance.Objects.clear();
gWorldInstance.Emitters.clear();
gWorldInstance.Lakitus.clear();
Actors.clear();
StaticMeshActors.clear();
Objects.clear();
Emitters.clear();
Lakitus.clear();
}

View File

@ -52,21 +52,20 @@ typedef struct Matrix {
{}
};
private:
std::shared_ptr<Track> mTrack;
std::unique_ptr<Track> mTrack;
Cup* CurrentCup;
public:
static World* Instance;
explicit World();
~World();
RaceManager& GetRaceManager() { return *RaceManagerInstance; }
void SetRaceManager(std::unique_ptr<RaceManager> manager) { RaceManagerInstance = std::move(manager); }
std::shared_ptr<Track> AddTrack(std::shared_ptr<Track> track);
void TickCameras();
AActor* AddActor(AActor* actor);
AActor* AddActor(std::unique_ptr<AActor> actor);
struct Actor* AddBaseActor();
void ActorBeginPlay(Actor* actor);
AActor* GetActor(size_t index);
@ -76,9 +75,9 @@ public:
Actor* ConvertAActorToActor(AActor* actor);
void DrawStaticMeshActors();
StaticMeshActor* AddStaticMeshActor(std::string name, FVector pos, IRotator rot, FVector scale, std::string model, int32_t* collision);
StaticMeshActor* AddStaticMeshActor(const std::string& name, FVector pos, IRotator rot, FVector scale, const std::string& model, int32_t* collision);
OObject* AddObject(OObject* object);
OObject* AddObject(std::unique_ptr<OObject> object);
void TickObjects();
void TickObjects60fps();
@ -100,32 +99,16 @@ public:
u32 GetCupIndex();
u32 NextCup();
u32 PreviousCup();
void SetTrackFromCup();
World* GetWorld(void);
void CleanWorld(void);
// getter/setter for current track
std::shared_ptr<Track> GetTrack() {
return mTrack;
Track* GetTrack() {
return mTrack.get();
}
void SetCurrentTrack(std::shared_ptr<Track> track);
// These are only for browsing through the track list
void SetTrack(const char*);
template<typename T>
void SetTrackByType() {
for (const auto& track : Tracks) {
if (dynamic_cast<T*>(track.get())) {
SetCurrentTrack(track);
return;
}
}
printf("World::SetTrackByType() No track by the type found");
}
void NextTrack(void);
void PreviousTrack(void);
void SetCurrentTrack(std::unique_ptr<Track> track);
Matrix Mtx;
@ -134,24 +117,18 @@ public:
std::vector<GameCamera*> Cameras;
std::vector<StaticMeshActor*> StaticMeshActors;
std::vector<AActor*> Actors;
std::vector<OObject*> Objects;
std::vector<std::unique_ptr<StaticMeshActor>> StaticMeshActors;
std::vector<std::unique_ptr<AActor>> Actors;
std::vector<std::unique_ptr<OObject>> Objects;
std::vector<ParticleEmitter*> Emitters;
std::unordered_map<s32, OLakitu*> Lakitus;
/** Objects **/
PlayerBombKart playerBombKart[4]; // Used in battle mode
PlayerBombKart mPlayerBombKart[4]; // Used in battle mode
TrainCrossing* AddCrossing(Vec3f position, u32 waypointMin, u32 waypointMax, f32 approachRadius, f32 exitRadius);
std::vector<std::shared_ptr<TrainCrossing>> Crossings;
// Holds all available tracks
std::vector<std::shared_ptr<Track>> Tracks;
size_t TrackIndex = 0; // For browsing tracks.
private:
std::unique_ptr<RaceManager> RaceManagerInstance;
};
extern World gWorldInstance;

View File

@ -1,26 +1,35 @@
#include "BowserStatue.h"
#include <libultra/gbi.h>
#include "engine/Matrix.h"
#include "port/interpolation/FrameInterpolation.h"
extern "C" {
#include "common_structs.h"
#include "math_util.h"
#include "main.h"
#include "assets/models/tracks/bowsers_castle/bowsers_castle_data.h"
#include "assets/models/tracks/bowsers_castle/bowsers_castle_displaylists.h"
}
Vtx gBowserStatueVtx[717];
Gfx gBowserStatueGfx[162];
ABowserStatue::ABowserStatue(FVector pos, ABowserStatue::Behaviour behaviour) {
ABowserStatue::ABowserStatue(const SpawnParams& params) {
Name = "Bowser Statue";
ResourceName = "mk:bowser_statue";
Pos = pos;
ABowserStatue::Behaviour _behaviour = behaviour;
FVector pos = params.Location.value_or(FVector(0, 0, 0));
Pos[0] = pos.x; Pos[1] = pos.y; Pos[2] = pos.z;
IRotator rot = params.Rotation.value_or(IRotator(0, 0, 0));
Rot[0] = rot.pitch; Rot[1] = rot.yaw; Rot[2] = rot.roll;
Scale = params.Scale.value_or(FVector(1.0f, 1.0f, 1.0f));
mBehaviour = static_cast<ABowserStatue::Behaviour>(params.Behaviour.value_or(0));
}
void ABowserStatue::Tick() {
switch(_behaviour) {
switch(mBehaviour) {
case DEFAULT:
break;
case CRUSH:
@ -30,18 +39,18 @@ void ABowserStatue::Tick() {
void ABowserStatue::Draw(Camera *camera) {
Mat4 mtx;
Vec3f pos;
pos[0] = Pos.x + 76;
pos[1] = Pos.y;
pos[2] = Pos.z + 1846;
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
FVector pos = FVector(Pos[0] + 76, Pos[1], Pos[2] + 1846);
mtxf_pos_rotation_xyz(mtx, pos, Rot);
if (render_set_position(mtx, 0) != 0) {
gSPDisplayList(gDisplayListHead++, gBowserStatueGfx);
}
FrameInterpolation_RecordOpenChild("mk:bowser_statue", TAG_OBJECT(this));
ApplyMatrixTransformations(mtx, pos, *(IRotator*)Rot, Scale);
AddObjectMatrix(mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gDPSetCombineMode(gDisplayListHead++,G_CC_MODULATEIA, G_CC_MODULATEIA);
gDPSetRenderMode(gDisplayListHead++,G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
gSPDisplayList(gDisplayListHead++,(Gfx*) d_course_bowsers_castle_packed_dl_2BB8);
FrameInterpolation_RecordCloseChild();
}
bool ABowserStatue::IsMod() { return true; }

View File

@ -17,20 +17,17 @@ extern Gfx gBowserStatueGfx[162];
// That generator is currently commented out. So this actor is not usable atm.
class ABowserStatue : public AActor {
public:
enum Behaviour {
enum Behaviour : int16_t {
DEFAULT,
CRUSH
};
virtual ~ABowserStatue() = default;
explicit ABowserStatue(FVector pos, ABowserStatue::Behaviour behaviour);
explicit ABowserStatue(const SpawnParams& params);
virtual void Tick() override;
virtual void Draw(Camera*) override;
virtual bool IsMod() override;
FVector Pos;
private:
ABowserStatue::Behaviour _behaviour;
f32 scale;
ABowserStatue::Behaviour mBehaviour;
};

View File

@ -17,7 +17,7 @@ extern f32 gKartGravityTable[];
}
ACloud::ACloud(const SpawnParams& params) : AActor(params) {
Name = "Cloud";
Name = "Cloud (HM64)";
ResourceName = "hm:cloud";
FVector pos = params.Location.value_or(FVector(0, 0, 0));
Pos[0] = pos.x;
@ -48,8 +48,10 @@ void ACloud::SetSpawnParams(SpawnParams& params) {
extern Gfx cloud_mesh[];
void ACloud::BeginPlay() {
// Prevent collision mesh from being generated extra times.
if (Triangles.size() == 0) {
Editor::GenerateCollisionMesh(this, (Gfx*)cloud_mesh, 1.0f);
if (Editor_IsEnabled()) {
if (Triangles.size() == 0) {
Editor::GenerateCollisionMesh(this, (Gfx*)cloud_mesh, 1.0f);
}
}
}
@ -87,7 +89,7 @@ void ACloud::Draw(Camera* camera) {
void ACloud::Collision(Player* player, AActor* actor) {
if (!PickedUp) {
if (query_collision_player_vs_actor_item(player, gWorldInstance.ConvertAActorToActor(actor))) {
if (query_collision_player_vs_actor_item(player, GetWorld()->ConvertAActorToActor(actor))) {
// Player has picked up the actor, activate the cloud effect
_player = player;
PickedUp = true;

View File

@ -1,13 +1,11 @@
#pragma once
#include <libultraship.h>
#include "RegisterContent.h"
#include "engine/Actor.h"
#include "CoreMath.h"
#include "engine/World.h"
extern "C" {
#include "macros.h"
#include "main.h"
#include "camera.h"
#include "common_structs.h"
}
@ -19,7 +17,7 @@ public:
virtual ~ACloud() override = default;
// This is simply a helper function to keep Spawning code clean
static inline ACloud* Spawn(FVector pos, uint16_t time, f32 hop, f32 gravity) {
static ACloud* Spawn(FVector pos, uint16_t time, f32 hop, f32 gravity) {
SpawnParams params = {
.Name = "hm:cloud",
.Type = time, // How long the effect is active
@ -27,7 +25,7 @@ public:
.Speed = hop, // How high you hop
.SpeedB = gravity, // How much gravity is effected
};
return static_cast<ACloud*>(gWorldInstance.AddActor(new ACloud(params)));
return dynamic_cast<ACloud*>(AddActorToWorld<ACloud>(params));
}
virtual void Tick() override;

View File

@ -1,18 +1,11 @@
#pragma once
#include <libultraship.h>
#include "RegisterContent.h"
#include "engine/Actor.h"
#include "CoreMath.h"
#include "engine/SpawnParams.h"
#include "engine/CoreMath.h"
#include "engine/World.h"
class World;
extern World gWorldInstance;
extern "C" {
#include "common_structs.h"
}
// Falls from the sky bouncing off of geography until it goes through water.
// Then after a brief period of time, respawns.
@ -26,13 +19,13 @@ public:
// This is simply a helper function to keep Spawning code clean
// @arg respawnTimer default game used 60, 120, 180 as the timer. Time until respawn after reaching the bottom?
static inline AFallingRock* Spawn(FVector pos, int16_t respawnTimer) {
static AFallingRock* Spawn(FVector pos, int16_t respawnTimer) {
SpawnParams params = {
.Name = "mk:falling_rock",
.Behaviour = respawnTimer,
.Location = pos,
};
return static_cast<AFallingRock*>(gWorldInstance.AddActor(new AFallingRock(params)));
return dynamic_cast<AFallingRock*>(AddActorToWorld<AFallingRock>(params));
}
int16_t TimerLength = 80;

View File

@ -51,8 +51,10 @@ AFinishline::AFinishline(const SpawnParams& params) : AActor(params) {
void AFinishline::BeginPlay() {
// Prevent collision mesh from being generated extra times.
if (Triangles.size() == 0) {
Editor::GenerateCollisionMesh(this, (Gfx*)LOAD_ASSET_RAW(D_0D001B90), 1.0f);
if (Editor_IsEnabled()) {
if (Triangles.size() == 0) {
Editor::GenerateCollisionMesh(this, (Gfx*)LOAD_ASSET_RAW(D_0D001B90), 1.0f);
}
}
}
@ -79,15 +81,15 @@ void AFinishline::Draw(Camera *camera) {
}
if (temp < camera->pos[2]) {
if (D_800DC5BC != 0) {
if (bFog) {
gDPSetFogColor(gDisplayListHead++, D_801625EC, D_801625F4, D_801625F0, 0xFF);
gDPSetFogColor(gDisplayListHead++, gFogColour.r, gFogColour.g, gFogColour.b, 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);
} else if (bFog) {
gDPSetFogColor(gDisplayListHead++, gFogColour.r, gFogColour.g, gFogColour.b, 0xFF);
gSPDisplayList(gDisplayListHead++, (Gfx*) D_0D001C88);
} else {
gSPDisplayList(gDisplayListHead++, (Gfx*) D_0D001BD8);

View File

@ -2,12 +2,10 @@
#include <libultraship.h>
#include "CoreMath.h"
#include "RegisterContent.h"
#include "engine/Actor.h"
#include "engine/World.h"
extern "C" {
#include "macros.h"
#include "main.h"
#include "camera.h"
#include "common_structs.h"
}
@ -25,20 +23,20 @@ public:
}
// This is simply a helper function to keep Spawning code clean
static inline AFinishline* Spawn(FVector pos, IRotator rot) {
static AFinishline* Spawn(FVector pos, IRotator rot) {
SpawnParams params = {
.Name = "mk:finishline",
.Location = pos,
.Rotation = rot,
};
return static_cast<AFinishline*>(gWorldInstance.AddActor(new AFinishline(params)));
return dynamic_cast<AFinishline*>(AddActorToWorld<AFinishline>(params));
}
static inline AFinishline* Spawn() {
static AFinishline* Spawn() {
SpawnParams params = {
.Name = "mk:finishline",
};
return static_cast<AFinishline*>(gWorldInstance.AddActor(new AFinishline(params)));
return dynamic_cast<AFinishline*>(AddActorToWorld<AFinishline>(params));
}
// Virtual functions to be overridden by derived classes

View File

@ -2,6 +2,7 @@
#include <libultra/gbi.h>
#include <assets/models/tracks/mario_raceway/mario_raceway_data.h>
#include "port/interpolation/FrameInterpolation.h"
#include "CoreMath.h"
extern "C" {
@ -72,6 +73,7 @@ void AMarioSign::Draw(Camera *camera) {
unk = MAX(unk, 0.0f);
}
if (!(unk < 0.0f)) {
FrameInterpolation_RecordOpenChild("mk:mario_sign", TAG_OBJECT(this));
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
mtxf_pos_rotation_xyz(sp40, Pos, Rot);
@ -79,5 +81,6 @@ void AMarioSign::Draw(Camera *camera) {
if (render_set_position(sp40, 0) != 0) {
gSPDisplayList(gDisplayListHead++, (Gfx*)d_course_mario_raceway_dl_sign);
}
FrameInterpolation_RecordCloseChild();
}
}

View File

@ -4,9 +4,7 @@
#include "engine/Actor.h"
#include "CoreMath.h"
#include "engine/World.h"
class World;
extern World gWorldInstance;
#include "RegisterContent.h"
extern "C" {
#include "common_structs.h"
@ -28,7 +26,7 @@ public:
.Velocity = velocity,
.Speed = 182,
};
return static_cast<AMarioSign*>(gWorldInstance.AddActor(new AMarioSign(params)));
return static_cast<AMarioSign*>(AddActorToWorld<AMarioSign>(params));
}
virtual bool IsMod() override;

View File

@ -26,15 +26,15 @@ AShip::AShip(const SpawnParams& params) : AActor(params) {
SpawnSkin = static_cast<AShip::Skin>(params.Type.value_or(0));
switch(SpawnSkin) {
case Skin::GHOSTSHIP:
Name = "Ghostship";
Name = "Ghostship (HM64)";
_skin = ghostship_Plane_mesh;
break;
case Skin::SHIP2:
Name = "Ship_1";
Name = "Ship 1 (HM64)";
_skin = ship2_SoH_mesh;
break;
case Skin::SHIP3:
Name = "Ship_2";
Name = "Ship 2 (HM64)";
_skin = ship3_2Ship_mesh;
break;
}
@ -53,8 +53,10 @@ void AShip::SetSpawnParams(SpawnParams& params) {
void AShip::BeginPlay() {
// Prevent collision mesh from being generated extra times.
if (Triangles.size() == 0) {
Editor::GenerateCollisionMesh(this, (Gfx*)_skin, Scale.y);
if (Editor_IsEnabled()) {
if (Triangles.size() == 0) {
Editor::GenerateCollisionMesh(this, (Gfx*)_skin, Scale.y);
}
}
}

View File

@ -3,18 +3,13 @@
#include <libultraship.h>
#include <libultra/gbi.h>
#include "CoreMath.h"
#include "RegisterContent.h"
#include "engine/Actor.h"
#include "engine/World.h"
extern "C" {
#include "common_structs.h"
#include "assets/textures/other_textures.h"
}
class AShip : public AActor {
public:
enum Skin {
enum Skin : int16_t {
GHOSTSHIP,
SHIP2,
SHIP3,
@ -24,7 +19,7 @@ public:
virtual ~AShip() = default;
// This is simply a helper function to keep Spawning code clean
static inline AShip* Spawn(FVector pos, IRotator rot, FVector scale, int16_t skin) {
static AShip* Spawn(FVector pos, IRotator rot, FVector scale, int16_t skin) {
SpawnParams params = {
.Name = "hm:ship",
.Type = skin, // which ship model to use
@ -32,7 +27,7 @@ public:
.Rotation = rot,
.Scale = scale,
};
return static_cast<AShip*>(gWorldInstance.AddActor(new AShip(params)));
return dynamic_cast<AShip*>(AddActorToWorld<AShip>(params));
}
AShip::Skin SpawnSkin = Skin::GHOSTSHIP;

View File

@ -3,6 +3,7 @@
#include <libultraship.h>
#include <libultra/gbi.h>
#include "CoreMath.h"
#include "RegisterContent.h"
#include "engine/Actor.h"
#include "engine/World.h"
@ -24,7 +25,7 @@ public:
.Rotation = rot,
.Scale = scale,
};
return static_cast<ASpaghettiShip*>(gWorldInstance.AddActor(new ASpaghettiShip(params)));
return static_cast<ASpaghettiShip*>(AddActorToWorld<ASpaghettiShip>(params));
}
virtual void Tick() override;

View File

@ -33,8 +33,10 @@ void AStarship::SetSpawnParams(SpawnParams& params) {
void AStarship::BeginPlay() {
// Prevent collision mesh from being generated extra times.
if (Triangles.size() == 0) {
Editor::GenerateCollisionMesh(this, (Gfx*)Model, 1.0f);
if (Editor_IsEnabled()) {
if (Triangles.size() == 0) {
Editor::GenerateCollisionMesh(this, (Gfx*)Model, 1.0f);
}
}
}

View File

@ -3,6 +3,7 @@
#include <libultraship.h>
#include <libultra/gbi.h>
#include "CoreMath.h"
#include "RegisterContent.h"
#include "engine/Actor.h"
#include "engine/World.h"
@ -17,7 +18,7 @@ public:
virtual ~AStarship() = default;
// This is simply a helper function to keep Spawning code clean
static inline AStarship* Spawn(FVector pos, IRotator rot, FVector scale, f32 speed, f32 radius) {
static AStarship* Spawn(FVector pos, IRotator rot, FVector scale, f32 speed, f32 radius) {
SpawnParams params = {
.Name = "hm:starship",
.Location = pos,
@ -26,7 +27,7 @@ public:
.Speed = speed,
.SpeedB = radius,
};
return static_cast<AStarship*>(gWorldInstance.AddActor(new AStarship(params)));
return dynamic_cast<AStarship*>(AddActorToWorld<AStarship>(params));
}
float SpeedB;

View File

@ -1,10 +1,10 @@
#pragma once
#include <libultraship.h>
#include "RegisterContent.h"
#include "engine/Actor.h"
#include "src/textures.h"
#include "engine/CoreMath.h"
#include "port/Game.h"
class AText : public AActor {
public:
@ -97,16 +97,16 @@ public:
* For transparency {0, 0, 0, 100} <-- alpha value of 100 will render semi-transparent black text.
*
*/
static inline AText* Spawn(std::string text, FVector pos, FVector scale, AText::TextMode textMode, int16_t playerIndex) {
static AText* Spawn(std::string text, FVector pos, FVector scale, AText::TextMode textMode, int16_t playerIndex) {
SpawnParams params = {
.Name = "hm:text",
.Type = static_cast<int16_t>(textMode),
.Behaviour = static_cast<int16_t>(playerIndex),
.Behaviour = playerIndex,
.Skin = text,
.Location = pos,
.Scale = scale,
};
return static_cast<AText*>(gWorldInstance.AddActor(new AText(params)));
return dynamic_cast<AText*>(AddActorToWorld<AText>(params));
}
// Virtual functions to be overridden by derived classes

View File

@ -2,6 +2,7 @@
#include <libultra/gbi.h>
#include <assets/models/tracks/wario_stadium/wario_stadium_data.h>
#include "port/interpolation/FrameInterpolation.h"
extern "C" {
#include "common_structs.h"
@ -53,6 +54,7 @@ void AWarioSign::Draw(Camera *camera) {
unk = MAX(unk, 0.0f);
}
if (!(unk < 0.0f)) {
FrameInterpolation_RecordOpenChild("mk:mario_sign", TAG_OBJECT(this));
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
@ -61,5 +63,6 @@ void AWarioSign::Draw(Camera *camera) {
gSPDisplayList(gDisplayListHead++, (Gfx*)d_course_wario_stadium_dl_sign);
}
FrameInterpolation_RecordCloseChild();
}
}

View File

@ -1,13 +1,9 @@
#pragma once
#include <libultraship.h>
#include "RegisterContent.h"
#include "engine/Actor.h"
#include "CoreMath.h"
#include "engine/World.h"
extern "C" {
#include "common_structs.h"
}
class AWarioSign : public AActor {
public:
@ -16,7 +12,7 @@ public:
explicit AWarioSign(const SpawnParams& params);
// This is simply a helper function to keep Spawning code clean
static inline AWarioSign* Spawn(FVector pos, IRotator rot, FVector velocity, FVector scale) {
static AWarioSign* Spawn(FVector pos, IRotator rot, FVector velocity, FVector scale) {
SpawnParams params = {
.Name = "mk:wario_sign",
.Location = pos,
@ -25,7 +21,7 @@ public:
.Velocity = velocity,
.Speed = 182,
};
return static_cast<AWarioSign*>(gWorldInstance.AddActor(new AWarioSign(params)));
return dynamic_cast<AWarioSign*>(AddActorToWorld<AWarioSign>(params));
}
virtual bool IsMod() override;

View File

@ -45,12 +45,12 @@ void TourCamera::Reset() {
void TourCamera::NextShot() {
TourCamera::Reset();
bShotComplete = false;
_camera->pos[0] = gWorldInstance.GetTrack()->TourShots[ShotIndex].Pos.x;
_camera->pos[1] = gWorldInstance.GetTrack()->TourShots[ShotIndex].Pos.y;
_camera->pos[2] = gWorldInstance.GetTrack()->TourShots[ShotIndex].Pos.z;
_camera->lookAt[0] = gWorldInstance.GetTrack()->TourShots[ShotIndex].LookAt.x;
_camera->lookAt[1] = gWorldInstance.GetTrack()->TourShots[ShotIndex].LookAt.y;
_camera->lookAt[2] = gWorldInstance.GetTrack()->TourShots[ShotIndex].LookAt.z;
_camera->pos[0] = GetWorld()->GetTrack()->TourShots[ShotIndex].Pos.x;
_camera->pos[1] = GetWorld()->GetTrack()->TourShots[ShotIndex].Pos.y;
_camera->pos[2] = GetWorld()->GetTrack()->TourShots[ShotIndex].Pos.z;
_camera->lookAt[0] = GetWorld()->GetTrack()->TourShots[ShotIndex].LookAt.x;
_camera->lookAt[1] = GetWorld()->GetTrack()->TourShots[ShotIndex].LookAt.y;
_camera->lookAt[2] = GetWorld()->GetTrack()->TourShots[ShotIndex].LookAt.z;
}
void TourCamera::Stop() {
@ -76,7 +76,7 @@ void TourCamera::Tick() {
if (
(nullptr == _camera) ||
(bTourComplete) ||
(ShotIndex >= gWorldInstance.GetTrack()->TourShots.size())
(ShotIndex >= GetWorld()->GetTrack()->TourShots.size())
) {
Alpha += 5;
if (Alpha == 255) {
@ -108,7 +108,7 @@ void TourCamera::Tick() {
}
}
bool done = TourCamera::MoveCameraAlongSpline(&extraArg, gWorldInstance.GetTrack()->TourShots[ShotIndex].Frames);
bool done = TourCamera::MoveCameraAlongSpline(&extraArg, GetWorld()->GetTrack()->TourShots[ShotIndex].Frames);
// Advance to the next camera shot
if (done) {

View File

@ -7,6 +7,7 @@
#include "engine/Actor.h"
#include "engine/objects/Object.h"
#include "engine/editor/GameObject.h"
#include "port/Game.h"
extern "C" {
#include "main.h"
@ -24,11 +25,6 @@ namespace Editor {
size_t i = 0;
bool run = true;
//! @attention Objects will not be clickable if editor is enabled mid-race.
if (CVarGetInteger("gEditorEnabled", false) == true) {
return;
}
while (run) {
i++;
lo = ptr->words.w0;

View File

@ -12,6 +12,7 @@
#include <ship/controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h>
#include <ship/window/Window.h>
#include "engine/TrackBrowser.h"
#include "engine/actors/Ship.h"
#include "port/Game.h"
@ -24,7 +25,10 @@ extern "C" {
}
namespace Editor {
Editor* Editor::Instance;
Editor::Editor() {
Instance = this;
}
Editor::~Editor() {
@ -43,28 +47,65 @@ namespace Editor {
printf("Editor: Loading Complete!\n");
}
void Editor::Enable() {
bEditorEnabled = true;
bIsEditorPaused = true;
CVarSetInteger("gFreecam", true);
CM_SetFreeCamera(true);
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Tools")->Show();
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Scene Explorer")->Show();
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Content Browser")->Show();
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Track Properties")->Show();
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Properties")->Show();
}
void Editor::Disable() {
bEditorEnabled = false;
bIsEditorPaused = false;
CVarSetInteger("gFreecam", false);
CM_SetFreeCamera(false);
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Tools")->Hide();
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Scene Explorer")->Hide();
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Content Browser")->Hide();
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Track Properties")->Hide();
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Properties")->Hide();
}
bool Editor::IsEnabled() {
return bEditorEnabled;
}
void Editor::Play() {
bIsEditorPaused = false;
}
void Editor::Pause() {
bIsEditorPaused = true;
}
bool Editor::IsPaused() {
return bIsEditorPaused;
}
void Editor::TogglePlayState() {
bIsEditorPaused = !bIsEditorPaused;
}
void Editor::GenerateCollision() {
// for (auto& actor : gWorldInstance.Actors) {
// for (auto& actor : GetWorld()->Actors) {
// GenerateCollisionMesh(actor, (Gfx*)actor->Model, 1.0f);
// }
}
void Editor::Tick() {
if (CVarGetInteger("gEditorEnabled", 0) == true) {
if (Editor_IsEnabled() == true) {
bEditorEnabled = true;
} else {
bEditorEnabled = false;
gIsEditorPaused = false; // Prevents game being paused with the editor closed.
bIsEditorPaused = false; // Prevents game being paused with the editor closed.
return;
}
// Set camera
if (CVarGetInteger("gFreecam", 0) == true) {
eCamera = &cameras[CAMERA_FREECAM];
} else {
eCamera = &cameras[0];
}
auto wnd = GameEngine::Instance->context->GetWindow();
static bool wasMouseDown = false;
@ -111,7 +152,6 @@ namespace Editor {
if (!isDragging) {
eObjectPicker.SelectObject(eGameObjects);
}
}
wasMouseDown = isMouseDown; // Update previous state
@ -197,3 +237,24 @@ namespace Editor {
eObjectPicker.eGizmo.dimensions.MaxZ = maxZ + 1000;
}
}
/** C BRIDGE FUNCTIONS **/
extern "C" void Editor_Launch(const char* resourceName) {
#if not defined(__SWITCH__) and not defined(__WIIU__)
TrackBrowser::Instance->SetTrack(std::string(resourceName));
gEditor.Enable();
#endif
}
extern "C" void Editor_SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY) {
gEditor.SetLevelDimensions(minX, maxX, minZ, maxZ, minY, maxY);
}
extern "C" bool Editor_IsEnabled() {
return gEditor.IsEnabled();
}
extern "C" bool Editor_IsPaused() {
return gEditor.IsPaused();
}

View File

@ -1,12 +1,12 @@
#ifndef __EDITOR_H__
#define __EDITOR_H__
#ifndef EDITOR_H
#define EDITOR_H
#include <libultraship/libultraship.h>
#include <libultra/gbi.h>
#include "GameObject.h"
#ifdef __cplusplus
#include "GameObject.h"
extern "C" {
#include "camera.h"
}
@ -17,15 +17,23 @@ namespace Editor {
class Editor {
public:
static Editor* Instance;
Editor();
~Editor();
ObjectPicker eObjectPicker;
std::vector<GameObject*> eGameObjects;
void Load();
void Enable();
void Disable();
bool IsEnabled();
void Play();
void Pause();
bool IsPaused();
void TogglePlayState();
void Tick();
void Draw();
void Load();
void GenerateCollision();
GameObject* AddObject(FVector pos, IRotator rot, FVector scale, const char* model, float collScale, GameObject::CollisionType collision, float boundingBoxSize);
void AddLight(const char* name, FVector* pos, s8* rot);
@ -36,10 +44,9 @@ public:
void SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY);
void ClearMatrixPool();
void DeleteObject();
bool bEditorEnabled = false;
Camera* eCamera = &cameras[0];
private:
bool bIsEditorPaused = false;
bool bEditorEnabled = false;
bool _draw = false;
Vec3f _ray;
@ -47,9 +54,19 @@ private:
void Copy(MtxF* src, MtxF* dest);
void Clear(MtxF* mf);
};
}
} // namespace Editor
#endif // __cplusplus
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif
void SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY);
EXTERN_C void Editor_Launch(const char* resourceName);
EXTERN_C void Editor_SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY);
EXTERN_C bool Editor_IsEnabled();
EXTERN_C bool Editor_IsPaused();
#endif // __EDITOR_H__
#endif // EDITOR_H

View File

@ -42,7 +42,7 @@ bool IsInGameScreen() {
FVector ScreenRayTrace() {
auto wnd = GameEngine::Instance->context->GetWindow();
Camera* camera = gEditor.eCamera;
Camera* camera = gScreenOneCtx->camera;
Ship::Coords mouse = wnd->GetMousePos();
auto gfx_current_game_window_viewport = GetInterpreter()->mGameWindowViewport;
@ -62,7 +62,7 @@ FVector ScreenRayTrace() {
Mat4 perspMtx;
u16 perspNorm;
guPerspectiveF(perspMtx, &perspNorm, gCameraFOV[0], OTRGetAspectRatio(), CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f);
guPerspectiveF(perspMtx, &perspNorm, 40, OTRGetAspectRatio(), CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f);
Mat4 inversePerspMtx;
if (InverseMatrix((float*)&perspMtx, (float*)&inversePerspMtx) != 2) {
@ -412,7 +412,7 @@ void SetRotatorFromDirection(FVector direction, IRotator* rot) {
}
FVector GetPositionAheadOfCamera(f32 dist) {
Camera* camera = gEditor.eCamera;
Camera* camera = gScreenOneCtx->camera;
FVector pos = FVector(camera->pos[0], camera->pos[1], camera->pos[2]);
f32 pitch = (camera->rot[2] / 65535.0f) * 360.0f;

View File

@ -112,7 +112,7 @@ void Gizmo::Translate() {
static float length = 180.0f; // Default value
std::visit([this](auto* obj) {
Camera* camera = gEditor.eCamera;
Camera* camera = gScreenOneCtx->camera;
float x, y, z = 0;
if (nullptr == obj) {
return;
@ -217,7 +217,7 @@ f32 Gizmo::SnapToSurface(const FVector pos) {
void Gizmo::Rotate() {
std::visit([this](auto* obj) {
Camera* camera = gEditor.eCamera;
Camera* camera = gScreenOneCtx->camera;
FVector cam = FVector(camera->pos[0], camera->pos[1], camera->pos[2]);
IRotator rot;
@ -269,7 +269,7 @@ void Gizmo::Rotate() {
void Gizmo::Scale() {
std::visit([this](auto* obj) {
Camera* camera = gEditor.eCamera;
Camera* camera = gScreenOneCtx->camera;
FVector cam = FVector(camera->pos[0], camera->pos[1], camera->pos[2]);
if (nullptr == obj) {
return;
@ -398,7 +398,7 @@ void Gizmo::DrawHandles() {
Editor_AddMatrix(mainMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
if (center) {
Camera* camera = gEditor.eCamera;
Camera* camera = gScreenOneCtx->camera;
Mat4 CenterMtx;
Editor_MatrixIdentity(CenterMtx);

View File

@ -57,7 +57,7 @@ size_t LightObject::NumLights = 0;
SetDirectionFromRotator(Rot, Direction);
}
void LightObject::Draw() {
Camera* camera = gEditor.eCamera;
Camera* camera = gScreenOneCtx->camera;
Mat4 mtx_sun;
Editor_MatrixIdentity(mtx_sun);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);

View File

@ -35,7 +35,7 @@ void ObjectPicker::Tick() {
}
void ObjectPicker::SelectObject(std::vector<GameObject*> objects) {
Camera* camera = gEditor.eCamera;
Camera* camera = gScreenOneCtx->camera;
Ray ray;
ray.Origin = FVector(camera->pos[0], camera->pos[1], camera->pos[2]);
@ -59,7 +59,7 @@ void ObjectPicker::SelectObject(std::vector<GameObject*> objects) {
}
void ObjectPicker::DragHandle() {
Camera* camera = gEditor.eCamera;
Camera* camera = gScreenOneCtx->camera;
Ray ray;
ray.Origin = FVector(camera->pos[0], camera->pos[1], camera->pos[2]);
ray.Direction = ScreenRayTrace();
@ -136,7 +136,7 @@ void ObjectPicker::Draw() {
}, _selected);
if (Debug) {
Camera* camera = gEditor.eCamera;
Camera* camera = gScreenOneCtx->camera;
Mat4 CursorMtx;
IRotator rot = IRotator(0,0,0);
FVector scale = FVector(1, 1, 1);
@ -249,7 +249,7 @@ std::pair<AActor*, float> ObjectPicker::CheckAActorRay(Ray ray) {
AActor* hitActor = nullptr;
float hitDistance = FLT_MAX;
for (auto actor : gWorldInstance.Actors) {
for (const auto& actor : GetWorld()->Actors) {
if ((actor->bPendingDestroy) && (!actor->IsMod())) {
continue;
}
@ -265,7 +265,7 @@ std::pair<AActor*, float> ObjectPicker::CheckAActorRay(Ray ray) {
if (IntersectRayTriangleAndTransform(ray, FVector(actor->Pos[0], actor->Pos[1], actor->Pos[2]), tri, t)) {
if (t < hitDistance) {
hitDistance = t;
hitActor = static_cast<AActor*>(actor);
hitActor = actor.get();
}
}
}
@ -283,7 +283,7 @@ std::pair<AActor*, float> ObjectPicker::CheckAActorRay(Ray ray) {
if (QueryCollisionRayActor(&ray.Origin.x, &ray.Direction.x, boxMin, boxMax, &t)) {
if (t < hitDistance) {
hitDistance = t;
hitActor = static_cast<AActor*>(actor);
hitActor = actor.get();
}
}
}

View File

@ -7,6 +7,7 @@
#include <iostream>
#include <fstream>
#include <memory>
#include <optional> // Must be before json.hpp
#include <nlohmann/json.hpp>
#include "port/Engine.h"
@ -21,28 +22,23 @@
#include "engine/objects/Thwomp.h"
#include "engine/objects/Snowman.h"
#include "engine/cameras/TourCamera.h"
#include "port/resource/type/TrackPathPointData.h"
extern "C" {
#include "common_structs.h"
#include "actors.h"
#include "actor_types.h"
#include "code_80005FD0.h"
}
namespace Editor {
std::shared_ptr<Ship::Archive> CurrentArchive;
std::string SceneFile = "";
void SaveLevel() {
if ((!CurrentArchive) || (SceneFile.empty())) {
SPDLOG_INFO("[SceneManager] [SaveLevel] Could not save scene file, SceneFile or CurrentArchive not set");
return;
}
void SaveLevel(Track* track) {
nlohmann::json data;
/**
* Save track properties, static mesh actors, actors, and tour camera
*/
data["Props"] = gWorldInstance.GetTrack()->Props.to_json();
data["Props"] = track->Props.to_json();
nlohmann::json staticMesh;
SaveStaticMeshActors(staticMesh);
@ -54,12 +50,17 @@ namespace Editor {
data["Actors"] = actors;
if (gWorldInstance.GetTrack()->TourShots.size() != 0) {
if (track->TourShots.size() != 0) {
nlohmann::json tour;
SaveTour(tour);
SaveTour(track, tour);
data["Tour"] = tour;
}
if (nullptr == track->Archive) {
SPDLOG_INFO("[SceneManager] [SaveLevel] Track archive nullptr");
return;
}
/**
* Write data to file
*/
@ -68,11 +69,14 @@ namespace Editor {
std::vector<uint8_t> bytes; // Turn the str into raw data
bytes.assign(jsonStr.begin(), jsonStr.end());
const TrackInfo* info = gTrackRegistry.GetInfo(track->ResourceName);
std::string sceneFile = info->Path + "/scene.json";
// Write file to disk
bool wrote = GameEngine::Instance->context->GetResourceManager()->GetArchiveManager()->WriteFile(CurrentArchive, SceneFile, bytes);
bool wrote = GameEngine::Instance->context->GetResourceManager()->GetArchiveManager()->WriteFile(track->Archive, sceneFile, bytes);
if (wrote) {
// Tell the cache this file needs to be reloaded
auto resource = GameEngine::Instance->context->GetResourceManager()->GetCachedResource(SceneFile);
auto resource = GameEngine::Instance->context->GetResourceManager()->GetCachedResource(sceneFile);
if (resource) {
resource->Dirty();
}
@ -84,11 +88,18 @@ namespace Editor {
}
}
/** Do not use gWorldInstance.CurrentCourse during loading! The current track is not guaranteed! **/
void LoadLevel(Track* track, std::string sceneFile) {
SceneFile = sceneFile;
if ((nullptr == track) || (nullptr == track->RootArchive)) {
SPDLOG_INFO("[SceneManager] [LoadLevel] Failed to load scenefile, track or rootarchive were null");
/** Do not use GetWorld()->CurrentCourse during loading! The current track is not guaranteed! **/
void LoadTrackDataFromJson(Track* track, const std::string& trackPath) {
SPDLOG_INFO("[SceneManager] [LoadTrackDataFromJson] Loading track scenefile...");
if (trackPath.empty()) {
SPDLOG_INFO(" Unable to load track. trackPath empty.");
return;
}
std::string sceneFile = trackPath + "/scene.json";
if ((nullptr == track) || (nullptr == track->Archive)) {
SPDLOG_INFO(" Failed to load scenefile, track or archive were null");
return;
}
@ -97,7 +108,7 @@ namespace Editor {
* the init data needs to be manually populated
*/
auto initData = std::make_shared<Ship::ResourceInitData>();
initData->Parent = track->RootArchive;
initData->Parent = track->Archive;
initData->Format = RESOURCE_FORMAT_BINARY;
initData->ByteOrder = Ship::Endianness::Little;
initData->Type = static_cast<uint32_t>(Ship::ResourceType::Json);
@ -109,56 +120,80 @@ namespace Editor {
// Check that the data is valid
if (data.is_null() || !data.is_object() || data.empty()) {
SPDLOG_INFO("[SceneManager] [LoadLevel] Scenefile corrupted or contained no data");
SPDLOG_INFO(" Scenefile corrupted or contained no data");
return;
}
SPDLOG_INFO("[SceneManager] [LoadLevel] Loading track scenefile...");
SPDLOG_INFO(" Loading Props, Actors, Static Mesh Actors, and Tour...");
// Load the Props, and populate actors
LoadProps(track, data);
LoadPaths(track, trackPath);
LoadMinimap(track, trackPath);
LoadActors(track, data);
LoadStaticMeshActors(track, data);
LoadTour(track, data);
SPDLOG_INFO("[SceneManager] [LoadLevel] Scene File Loaded!");
SPDLOG_INFO("[SceneManager] [LoadTrackDataFromJson] Scene File Loaded!");
}
void LoadTrackInfo(TrackInfo& info, std::shared_ptr<Ship::Archive> archive, std::string sceneFile) {
if (nullptr == archive) {
SPDLOG_INFO("[SceneManager] [LoadTrackDataFromJson] Failed to load scenefile, track or rootarchive were null");
return;
}
/*
* Manually loading a custom asset file (scene.json) with no extractor class means that
* the init data needs to be manually populated
*/
auto initData = std::make_shared<Ship::ResourceInitData>();
initData->Parent = archive;
initData->Format = RESOURCE_FORMAT_BINARY;
initData->ByteOrder = Ship::Endianness::Little;
initData->Type = static_cast<uint32_t>(Ship::ResourceType::Json);
initData->ResourceVersion = 0;
// Load the scene file and return the json data
nlohmann::json data = std::static_pointer_cast<Ship::Json>(
GameEngine::Instance->context->GetResourceManager()->LoadResource(sceneFile, true, initData))->Data;
// Check that the data is valid
if (data.is_null() || !data.is_object() || data.empty()) {
SPDLOG_INFO("[SceneManager] [LoadTrackInfo] Scenefile corrupted or contained no data");
return;
}
LoadTrackInfoData(info, data);
SPDLOG_INFO("[SceneManager] [LoadTrackInfo] Loaded track info!");
}
void Load_AddStaticMeshActor(const nlohmann::json& actorJson) {
gWorldInstance.StaticMeshActors.push_back(new StaticMeshActor("", FVector(0, 0, 0), IRotator(0, 0, 0), FVector(1, 1, 1), "", nullptr));
auto actor = gWorldInstance.StaticMeshActors.back();
GetWorld()->StaticMeshActors.push_back(std::make_unique<StaticMeshActor>("", FVector(0, 0, 0), IRotator(0, 0, 0), FVector(1, 1, 1), "", nullptr));
auto& actor = GetWorld()->StaticMeshActors.back();
actor->from_json(actorJson);
printf("After from_json: Pos(%f, %f, %f), Name: %s, Model: %s\n",
actor->Pos.x, actor->Pos.y, actor->Pos.z, actor->Name.c_str(), actor->Model.c_str());
}
void SetSceneFile(std::shared_ptr<Ship::Archive> archive, std::string sceneFile) {
CurrentArchive = archive;
SceneFile = sceneFile;
}
// Called from ContentBrowser.cpp
void LoadMinimap(Track* track, std::string filePath) {
std::string minimapPath = filePath + "/minimap.png";
SPDLOG_INFO(" Loading {} minimap...", filePath);
if (nullptr == track->RootArchive) {
SPDLOG_INFO("[SceneManager] [LoadMinimap] Root archive is nullptr");
SetDefaultMinimap(track);
return;
}
/*
* Manually loading a custom asset file with no extractor class means that
* the init data needs to be manually populated
*/
auto initData = std::make_shared<Ship::ResourceInitData>();
initData->Parent = track->RootArchive;
initData->Parent = track->Archive;
initData->Format = RESOURCE_FORMAT_BINARY;
initData->ByteOrder = Ship::Endianness::Little;
initData->Type = static_cast<uint32_t>(MK64::ResourceType::Minimap);
initData->ResourceVersion = 0;
std::shared_ptr<MK64::Minimap> ptr = std::static_pointer_cast<MK64::Minimap>(
GameEngine::Instance->context->GetResourceManager()->LoadResource(filePath, true, initData));
GameEngine::Instance->context->GetResourceManager()->LoadResource(minimapPath, true, initData));
if (ptr) {
SPDLOG_INFO(" Minimap Loaded!");
@ -180,7 +215,7 @@ namespace Editor {
}
void SaveActors(nlohmann::json& actorList) {
for (const auto& actor : gWorldInstance.Actors) {
for (const auto& actor : GetWorld()->Actors) {
SpawnParams params{};
bool alreadyProcessed = false;
@ -234,7 +269,7 @@ namespace Editor {
}
}
for (const auto& object : gWorldInstance.Objects) {
for (const auto& object : GetWorld()->Objects) {
SpawnParams params;
object->SetSpawnParams(params);
@ -247,17 +282,17 @@ namespace Editor {
}
void SaveStaticMeshActors(nlohmann::json& actorList) {
for (const auto& mesh : gWorldInstance.StaticMeshActors) {
for (const auto& mesh : GetWorld()->StaticMeshActors) {
actorList.push_back(mesh->to_json());
}
}
void SaveTour(nlohmann::json& tour) {
tour["Enabled"] = gWorldInstance.GetTrack()->bTourEnabled;
void SaveTour(Track* track, nlohmann::json& tour) {
tour["Enabled"] = track->bTourEnabled;
// Camera shots
tour["Shots"] = nlohmann::json::array();
for (const auto& shot : gWorldInstance.GetTrack()->TourShots) {
for (const auto& shot : track->TourShots) {
tour["Shots"].push_back(ToJson(shot));
}
}
@ -276,8 +311,58 @@ namespace Editor {
}
}
void LoadPaths(Track* track, const std::string& trackPath) {
std::string path_file = (trackPath + "/data_paths").c_str();
auto res = std::dynamic_pointer_cast<MK64::Paths>(ResourceLoad(path_file.c_str()));
if (res != nullptr) {
auto& paths = res->PathList;
size_t i = 0;
u16* ptr = &track->Props.PathSizes.unk0;
for (auto& path : paths) {
if (i >= ARRAY_COUNT(track->Props.PathTable2)) {
printf("[Track.cpp] The game can only import 5 paths. Found more than 5. Skipping the rest\n");
break; // Only 5 paths allowed. 4 track, 1 vehicle
}
ptr[i] = path.size();
track->Props.PathTable2[i] = (TrackPathPoint*) path.data();
i += 1;
}
}
gVehiclePathSize = track->Props.PathSizes.unk0; // This is likely incorrect.
}
void LoadTrackInfoData(TrackInfo& info, nlohmann::json& data) {
if (!data.contains("Props") || !data["Props"].is_object()) {
SPDLOG_INFO("[SceneManager] [LoadTrackInfoData] Track is missing props data. Is the scene.json file corrupt?");
return;
}
try {
nlohmann::json& j = data.at("Props");
info.ResourceName = j.at("ResourceName").get<std::string>();
info.Name = j.at("Name").get<std::string>();
info.DebugName = j.at("DebugName").get<std::string>();
info.Length = j.at("TrackLength").get<std::string>();
printf("[SceneManager] [LoadTrackInfoData] ResourceName: %s, Name: %s, DebugName: %s, Length: %s\n",
info.ResourceName.c_str(),
info.Name.c_str(),
info.DebugName.c_str(),
info.Length.c_str()
);
} catch(const std::exception& e) {
std::cerr << " Error parsing track properties: " << e.what() << std::endl;
std::cerr << " Is your scene.json file out of date?" << std::endl;
}
}
void LoadActors(Track* track, nlohmann::json& data) {
if (!data.contains("Actors") || !data["Actors"].is_object()) {
if (!data.contains("Actors") || !data["Actors"].is_array()) {
SPDLOG_INFO(" This track contains no actors");
return;
}
@ -294,12 +379,12 @@ namespace Editor {
}
void LoadStaticMeshActors(Track* track, nlohmann::json& data) {
if (!data.contains("StaticMeshActors") || !data["StaticMeshActors"].is_object()) {
if (!data.contains("StaticMeshActors") || !data["StaticMeshActors"].is_array()) {
SPDLOG_INFO(" This track contains no StaticMeshActors!");
return;
}
gWorldInstance.StaticMeshActors.clear(); // Clear existing actors, if any
GetWorld()->StaticMeshActors.clear(); // Clear existing actors, if any
for (const auto& actorJson : data["StaticMeshActors"]) {
Load_AddStaticMeshActor(actorJson);
@ -308,7 +393,7 @@ namespace Editor {
void LoadTour(Track* track, nlohmann::json& data) {
if (!data.contains("Tour") || !data["Tour"].is_object()) {
SPDLOG_INFO(" This track does not contain a camera tour");
SPDLOG_INFO(" This track does not contain a camera tour");
return;
}

View File

@ -7,28 +7,26 @@
#include <nlohmann/json.hpp>
namespace Editor {
void SaveLevel();
void LoadLevel(Track* track, std::string sceneFile);
void SaveLevel(Track* track);
void LoadTrackDataFromJson(Track* track, const std::string& trackPath);
void LoadTrackInfo(TrackInfo& info, std::shared_ptr<Ship::Archive> archive, std::string sceneFile);
void Load_AddStaticMeshActor(const nlohmann::json& actorJson);
void SetSceneFile(std::shared_ptr<Ship::Archive> archive, std::string sceneFile);
void LoadMinimap(Track* track, std::string filePath);
void SetDefaultMinimap(Track* track);
void SaveActors(nlohmann::json& actorList);
void SaveStaticMeshActors(nlohmann::json& actorList);
void SaveTour(nlohmann::json& tour);
void SaveTour(Track* track, nlohmann::json& tour);
void LoadProps(Track* track, nlohmann::json& data);
void LoadPaths(Track* track, const std::string& trackPath);
void LoadTrackInfoData(TrackInfo& info, nlohmann::json& data);
void LoadActors(Track* track, nlohmann::json& data);
void LoadStaticMeshActors(Track* track, nlohmann::json& data);
void LoadTour(Track* track, nlohmann::json& data);
void SpawnActors(std::vector<std::pair<std::string, SpawnParams>> spawnList);
extern std::shared_ptr<Ship::Archive> CurrentArchive; // This is used to retrieve and write the scene data file
extern std::string SceneFile;
inline nlohmann::json ToJson(const FVector& v) {
return {
{"x", v.x},

View File

@ -4,6 +4,7 @@
#include <vector>
#include "Object.h"
#include "RegisterContent.h"
#include "World.h"
#include "CoreMath.h"
@ -36,7 +37,7 @@ public:
.Location = pos,
.Rotation = rot,
};
return static_cast<OBat*>(gWorldInstance.AddObject(new OBat(params)));
return dynamic_cast<OBat*>(AddObjectToWorld<OBat>(params));
}
explicit OBat(const SpawnParams& params);

View File

@ -1,19 +1,13 @@
#pragma once
#include <libultraship.h>
#include "RegisterContent.h"
#include "engine/objects/Object.h"
#include <vector>
#include "engine/Matrix.h"
#include "World.h"
extern "C" {
#include "macros.h"
#include "main.h"
#include "vehicles.h"
#include "waypoints.h"
#include "common_structs.h"
#include "objects.h"
}
/**
@ -52,7 +46,7 @@ class OBombKart : public OObject {
// This is simply a helper function to keep Spawning code clean
// Spawn object at a position
static inline OBombKart* Spawn(FVector pos, uint16_t behaviour, f32 unk_3C) {
static OBombKart* Spawn(FVector pos, uint16_t behaviour, f32 unk_3C) {
SpawnParams params = {
.Name = "mk:bomb_kart",
.Behaviour = behaviour,
@ -60,11 +54,11 @@ class OBombKart : public OObject {
.Speed = unk_3C, // Only used for podium ceremony. Arbitrarily chose Speed for this
.SpeedB = 2.7f, // Chase speed
};
return static_cast<OBombKart*>(gWorldInstance.AddObject(new OBombKart(params)));
return dynamic_cast<OBombKart*>(AddObjectToWorld<OBombKart>(params));
}
// Spawn object at a point along the tracks path
static inline OBombKart* Spawn(uint32_t pathIndex, uint32_t pathPoint, uint16_t behaviour, f32 unk_3C) {
static OBombKart* Spawn(uint32_t pathIndex, uint32_t pathPoint, uint16_t behaviour, f32 unk_3C) {
SpawnParams params = {
.Name = "mk:bomb_kart",
.Behaviour = behaviour,
@ -72,7 +66,7 @@ class OBombKart : public OObject {
.PathPoint = pathPoint,
.Speed = unk_3C, // Only used for podium ceremony. Arbitrarily chose Speed for this
};
return static_cast<OBombKart*>(gWorldInstance.AddObject(new OBombKart(params)));
return dynamic_cast<OBombKart*>(AddObjectToWorld<OBombKart>(params));
}
// Set waypoint to NULL if using a spawn position and not a waypoint.

View File

@ -4,6 +4,7 @@
#include <vector>
#include "Object.h"
#include "RegisterContent.h"
#include "World.h"
#include "CoreMath.h"
@ -45,7 +46,7 @@ public:
.TriggerSpan = triggerBoundary,
.RightExitSpan = rightBoundary,
};
return static_cast<OBoos*>(gWorldInstance.AddObject(new OBoos(params)));
return static_cast<OBoos*>(AddObjectToWorld<OBoos>(params));
}
explicit OBoos(const SpawnParams& params);

View File

@ -29,6 +29,16 @@ OChainChomp::OChainChomp() {
_count++;
}
OChainChomp::OChainChomp(const SpawnParams& params) {
Name = "Chain Chomp";
ResourceName = "mk:chain_chomp";
_idx = _count;
init_object(indexObjectList2[_idx], 0);
_objectIndex = indexObjectList2[_idx];
_count++;
}
void OChainChomp::Tick() {
s32 objectIndex;
Object* object;

View File

@ -23,6 +23,7 @@ extern "C" {
class OChainChomp : public OObject {
public:
explicit OChainChomp();
explicit OChainChomp(const SpawnParams& params);
~OChainChomp() {

View File

@ -3,6 +3,7 @@
#include <libultraship.h>
#include <vector>
#include "Object.h"
#include "RegisterContent.h"
#include "engine/CoreMath.h"
#include "World.h"
@ -32,7 +33,7 @@ public:
.Location = pos,
.PathSpan = span,
};
return static_cast<OCheepCheep*>(gWorldInstance.AddObject(new OCheepCheep(params)));
return static_cast<OCheepCheep*>(AddObjectToWorld<OCheepCheep>(params));
}
explicit OCheepCheep(const SpawnParams& params);

View File

@ -2,6 +2,7 @@
#include <libultraship.h>
#include <vector>
#include "RegisterContent.h"
#include "engine/objects/Object.h"
#include "CoreMath.h"
#include "World.h"
@ -37,7 +38,7 @@ public:
.PatrolStart = start,
.PatrolEnd = end,
};
return static_cast<OCrab*>(gWorldInstance.AddObject(new OCrab(params)));
return static_cast<OCrab*>(AddObjectToWorld<OCrab>(params));
}
explicit OCrab(const SpawnParams& params);

View File

@ -4,6 +4,7 @@
#include <vector>
#include "Object.h"
#include "RegisterContent.h"
#include "World.h"
extern "C" {
@ -24,7 +25,7 @@ public:
explicit OFlagpole(const SpawnParams& params);
// This is simply a helper function to keep Spawning code clean
static inline OFlagpole* Spawn(FVector pos, s16 direction) {
static OFlagpole* Spawn(FVector pos, s16 direction) {
IRotator rot;
rot.Set(0, direction, 0);
SpawnParams params = {
@ -32,7 +33,7 @@ public:
.Location = pos,
.Rotation = rot,
};
return static_cast<OFlagpole*>(gWorldInstance.AddObject(new OFlagpole(params)));
return dynamic_cast<OFlagpole*>(AddObjectToWorld<OFlagpole>(params));
}
~OFlagpole() {

View File

@ -1,20 +1,13 @@
#pragma once
#include <libultraship.h>
#include <vector>
#include "RegisterContent.h"
#include "engine/World.h"
#include "engine/objects/Object.h"
extern "C" {
#include "macros.h"
#include "main.h"
#include "vehicles.h"
#include "waypoints.h"
#include "common_structs.h"
#include "objects.h"
#include "camera.h"
#include "some_data.h"
}
@ -28,12 +21,12 @@ public:
explicit OGrandPrixBalloons(const SpawnParams& params);
// This is simply a helper function to keep Spawning code clean
static inline OGrandPrixBalloons* Spawn(const FVector& pos) {
static OGrandPrixBalloons* Spawn(const FVector& pos) {
SpawnParams params = {
.Name = "mk:grand_prix_balloons",
.Location = pos,
};
return static_cast<OGrandPrixBalloons*>(gWorldInstance.AddObject(new OGrandPrixBalloons(params)));
return dynamic_cast<OGrandPrixBalloons*>(AddObjectToWorld<OGrandPrixBalloons>(params));
}
~OGrandPrixBalloons() {

View File

@ -4,6 +4,7 @@
#include <vector>
#include "Object.h"
#include "RegisterContent.h"
#include "engine/World.h"
extern "C" {
@ -34,7 +35,7 @@ public:
.Location = pos,
.PatrolEnd = patrolPoint,
};
return static_cast<OHedgehog*>(gWorldInstance.AddObject(new OHedgehog(params)));
return static_cast<OHedgehog*>(AddObjectToWorld<OHedgehog>(params));
}
~OHedgehog() {

View File

@ -1,33 +1,22 @@
#pragma once
#include <libultraship.h>
#include <vector>
#include "Object.h"
#include "RegisterContent.h"
#include "World.h"
extern "C" {
#include "macros.h"
#include "main.h"
#include "vehicles.h"
#include "waypoints.h"
#include "common_structs.h"
#include "objects.h"
#include "camera.h"
#include "some_data.h"
}
class OHotAirBalloon : public OObject {
public:
explicit OHotAirBalloon(const SpawnParams& params);
// This is simply a helper function to keep Spawning code clean
static inline OHotAirBalloon* Spawn(FVector pos) {
static OHotAirBalloon* Spawn(FVector pos) {
SpawnParams params = {
.Name = "mk:hot_air_balloon",
.Location = pos,
};
return static_cast<OHotAirBalloon*>(gWorldInstance.AddObject(new OHotAirBalloon(params)));
return dynamic_cast<OHotAirBalloon*>(AddObjectToWorld<OHotAirBalloon>(params));
}
virtual void Tick() override;

View File

@ -15,7 +15,7 @@ OMoleGroup::OMoleGroup(std::vector<FVector>& spawns, size_t tickRate) {
_tickRate = tickRate;
for (auto& pos : spawns) {
pos.x * xOrientation;
OMole* ptr = reinterpret_cast<OMole*>(gWorldInstance.AddObject(new OMole(pos, this)));
OMole* ptr = reinterpret_cast<OMole*>(GetWorld()->AddObject(std::make_unique<OMole>(pos, this)));
_moles.push_back({ptr, pos, false});
}

View File

@ -1,20 +1,10 @@
#pragma once
#include <libultraship.h>
#include <vector>
#include "RegisterContent.h"
#include "engine/World.h"
#include "engine/objects/Object.h"
extern "C" {
#include "macros.h"
#include "main.h"
#include "vehicles.h"
#include "waypoints.h"
#include "common_structs.h"
#include "objects.h"
#include "course_offsets.h"
}
class OPenguin : public OObject {
public:
enum PenguinType : int16_t {
@ -34,11 +24,10 @@ public:
SLIDE6,
};
public:
explicit OPenguin(const SpawnParams& params);
// This is simply a helper function to keep Spawning code clean
static inline OPenguin* Spawn(FVector pos, u16 direction, u16 mirrorModeAngleOffset, f32 diameter, PenguinType type, Behaviour behaviour) {
static OPenguin* Spawn(FVector pos, u16 direction, u16 mirrorModeAngleOffset, f32 diameter, PenguinType type, Behaviour behaviour) {
IRotator rot;
rot.Set(0, direction, mirrorModeAngleOffset);
SpawnParams params = {
@ -49,7 +38,7 @@ public:
.Rotation = rot,
.Speed = diameter, // Diameter of the walking circle
};
return static_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(params)));
return dynamic_cast<OPenguin*>(AddObjectToWorld<OPenguin>(params));
}
PenguinType Type = PenguinType::CHICK;

View File

@ -1,38 +1,25 @@
#pragma once
#include <libultraship.h>
#include <vector>
#include "RegisterContent.h"
#include "World.h"
extern "C" {
#include "macros.h"
#include "main.h"
#include "vehicles.h"
#include "waypoints.h"
#include "common_structs.h"
#include "objects.h"
#include "course_offsets.h"
#include "some_data.h"
}
class OPodium : public OObject {
public:
enum Behaviour : uint16_t {
};
public:
explicit OPodium(const SpawnParams& params);
// This is simply a helper function to keep Spawning code clean
static inline OPodium* Spawn(const FVector& pos) {
static OPodium* Spawn(const FVector& pos) {
SpawnParams params = {
.Name = "mk:podium",
.Location = pos,
};
return static_cast<OPodium*>(gWorldInstance.AddObject(new OPodium(params)));
return dynamic_cast<OPodium*>(AddObjectToWorld<OPodium>(params));
}
virtual void Tick() override;

View File

@ -1,21 +1,11 @@
#pragma once
#include <libultraship.h>
#include <vector>
#include "Object.h"
#include "RegisterContent.h"
#include "engine/World.h"
extern "C" {
#include "macros.h"
#include "main.h"
#include "vehicles.h"
#include "waypoints.h"
#include "common_structs.h"
#include "objects.h"
#include "camera.h"
}
//! @todo unk_0D5 needs to be a struct variable probably. What does it do? Behaviour?
class OSeagull : public OObject {
public:
@ -30,12 +20,12 @@ public:
}
// This is simply a helper function to keep Spawning code clean
static inline OSeagull* Spawn(const FVector& pos) {
static OSeagull* Spawn(const FVector& pos) {
SpawnParams params = {
.Name = "mk:seagull",
.Location = pos,
};
return static_cast<OSeagull*>(gWorldInstance.AddObject(new OSeagull(params)));
return dynamic_cast<OSeagull*>(AddObjectToWorld<OSeagull>(params));
}
virtual void Tick() override;

View File

@ -1,31 +1,24 @@
#pragma once
#include <libultraship.h>
#include <vector>
#include "Object.h"
#include "RegisterContent.h"
#include "World.h"
extern "C" {
#include "macros.h"
#include "main.h"
#include "vehicles.h"
#include "waypoints.h"
#include "common_structs.h"
#include "objects.h"
#include "camera.h"
#include "some_data.h"
}
class OSnowman : public OObject {
public:
// This is simply a helper function to keep Spawning code clean
static inline OSnowman* Spawn(FVector pos) {
static OSnowman* Spawn(FVector pos) {
SpawnParams params = {
.Name = "mk:snowman",
.Location = FVector(pos.x, pos.y, pos.z),
};
return static_cast<OSnowman*>(gWorldInstance.AddObject(new OSnowman(params)));
return dynamic_cast<OSnowman*>(AddObjectToWorld<OSnowman>(params));
}
explicit OSnowman(const SpawnParams& params);

View File

@ -1,25 +1,16 @@
#pragma once
#include <libultraship.h>
#include <vector>
#include "RegisterContent.h"
#include "engine/World.h"
#include "engine/SpawnParams.h"
#include "engine/CoreMath.h"
#include "engine/objects/Object.h"
class World;
extern World gWorldInstance;
extern "C" {
#include "macros.h"
#include "main.h"
#include "vehicles.h"
#include "waypoints.h"
#include "common_structs.h"
#include "objects.h"
#include "camera.h"
#include "some_data.h"
}
//! @todo Make shadow size bigger if thwomp is scaled up
@ -48,7 +39,7 @@ public:
};
// This is simply a helper function to keep Spawning code clean
static inline OThwomp* Spawn(s16 x, s16 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha, u16 boundingBoxSize = 7) {
static OThwomp* Spawn(s16 x, s16 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha, u16 boundingBoxSize = 7) {
IRotator rot;
rot.Set(0, direction, 0);
@ -61,7 +52,7 @@ public:
.PrimAlpha = primAlpha,
.BoundingBoxSize = boundingBoxSize
};
return static_cast<OThwomp*>(gWorldInstance.AddObject(new OThwomp(params)));
return dynamic_cast<OThwomp*>(AddObjectToWorld<OThwomp>(params));
}
explicit OThwomp(const SpawnParams& params);

View File

@ -1,22 +1,11 @@
#pragma once
#include <libultraship.h>
#include <vector>
#include "Object.h"
#include "RegisterContent.h"
#include "World.h"
extern "C" {
#include "macros.h"
#include "main.h"
#include "vehicles.h"
#include "waypoints.h"
#include "common_structs.h"
#include "objects.h"
#include "camera.h"
#include "some_data.h"
}
class OTrashBin : public OObject {
public:
@ -26,7 +15,7 @@ public:
};
// This is simply a helper function to keep Spawning code clean
static inline OTrashBin* Spawn(const FVector& pos, const IRotator& rot, f32 scale, OTrashBin::Behaviour bhv) {
static OTrashBin* Spawn(const FVector& pos, const IRotator& rot, f32 scale, OTrashBin::Behaviour bhv) {
SpawnParams params = {
.Name = "mk:trash_bin",
.Behaviour = bhv,
@ -34,7 +23,7 @@ public:
.Rotation = rot,
.Scale = FVector(0, scale, 0),
};
return static_cast<OTrashBin*>(gWorldInstance.AddObject(new OTrashBin(params)));
return dynamic_cast<OTrashBin*>(AddObjectToWorld<OTrashBin>(params));
}
explicit OTrashBin(const SpawnParams& params);

View File

@ -92,7 +92,7 @@ OTrophy::OTrophy(const SpawnParams& params) : OObject(params) {
object->pos[1] = spawnPos.y;
object->pos[2] = spawnPos.z;
_emitter = reinterpret_cast<StarEmitter*>(gWorldInstance.AddEmitter(new StarEmitter()));
_emitter = reinterpret_cast<StarEmitter*>(GetWorld()->AddEmitter(new StarEmitter()));
}
void OTrophy::SetSpawnParams(SpawnParams& params) {
@ -228,6 +228,11 @@ void OTrophy::Draw(s32 cameraId) {
Mat4 someMatrix1;
Mat4 someMatrix2;
Object* object;
if (Editor_IsPaused()) {
return;
}
if (*_toggleVisibility == true) {
object = &gObjectList[listIndex];
if (object->state >= 2) {

View File

@ -1,20 +1,13 @@
#pragma once
#include <libultraship.h>
#include <vector>
#include "Object.h"
#include "RegisterContent.h"
#include "World.h"
#include "engine/particles/StarEmitter.h"
extern "C" {
#include "macros.h"
#include "main.h"
#include "vehicles.h"
#include "waypoints.h"
#include "common_structs.h"
#include "objects.h"
#include "course_offsets.h"
#include "some_data.h"
}
class OTrophy : public OObject {
@ -37,14 +30,14 @@ public:
};
// This is simply a helper function to keep Spawning code clean
static inline OTrophy* Spawn(const FVector& pos, TrophyType trophy, Behaviour bhv) {
static OTrophy* Spawn(const FVector& pos, TrophyType trophy, Behaviour bhv) {
SpawnParams params = {
.Name = "mk:trophy",
.Type = trophy,
.Behaviour = bhv,
.Location = pos,
};
return static_cast<OTrophy*>(gWorldInstance.AddObject(new OTrophy(params)));
return dynamic_cast<OTrophy*>(AddObjectToWorld<OTrophy>(params));
}
explicit OTrophy(const SpawnParams& params);

View File

@ -16,6 +16,7 @@
#include "engine/objects/Boos.h"
#include "assets/models/tracks/banshee_boardwalk/banshee_boardwalk_data.h"
#include "assets/other/tracks/banshee_boardwalk/banshee_boardwalk_data.h"
#include "port/Game.h"
#include "assets/textures/boo_frames.h"
extern "C" {
@ -54,7 +55,7 @@ BansheeBoardwalk::BansheeBoardwalk() {
Props.Minimap.FinishlineY = 0;
ResizeMinimap(&Props.Minimap);
Id = "mk:banshee_boardwalk";
ResourceName = "mk:banshee_boardwalk";
Props.SetText(Props.Name, "banshee boardwalk", sizeof(Props.Name));
Props.SetText(Props.DebugName, "ghost", sizeof(Props.DebugName));
@ -141,19 +142,16 @@ void BansheeBoardwalk::Load() {
InvertTriangleWindingByName(d_course_banshee_boardwalk_packed_dl_878);
}
D_800DC5BC = 1;
D_801625EC = 0;
D_801625F4 = 0;
D_801625F0 = 0;
bFog = true;
gFogColour.r = 0;
gFogColour.g = 0;
gFogColour.b = 0;
gFogColour.a = 255;
parse_track_displaylists((TrackSections*) LOAD_ASSET_RAW(d_course_banshee_boardwalk_track_sections));
func_80295C6C();
find_vtx_and_set_colours((Gfx*) d_course_banshee_boardwalk_packed_dl_878, 128, 0, 0, 0);
}
void BansheeBoardwalk::UnLoad() {
RestoreTriangleWinding();
}
void BansheeBoardwalk::BeginPlay() {
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_banshee_boardwalk_item_box_spawns));
@ -168,25 +166,25 @@ void BansheeBoardwalk::BeginPlay() {
}
if (gIsMirrorMode) {
OTrashBin::Spawn(FVector(1765.0f, 45.0f, 195.0f), IRotator(0, 180, 0), 1.0f, bhv);
SpawnActor<OTrashBin>(FVector(1765.0f, 45.0f, 195.0f), IRotator(0, 180, 0), 1.0f, bhv);
} else {
OTrashBin::Spawn(FVector(-1765.0f, 45.0f, 70.0f), IRotator(0, 0, 0), 1.0f, bhv);
SpawnActor<OTrashBin>(FVector(-1765.0f, 45.0f, 70.0f), IRotator(0, 0, 0), 1.0f, bhv);
}
if ((gGamestate != CREDITS_SEQUENCE) && (gModeSelection != TIME_TRIALS)) {
OBat::Spawn(FVector(0,0,0), IRotator(0, 0, 90));
OBoos::Spawn(5, IPathSpan(180, 190), IPathSpan(200, 210), IPathSpan(280, 290));
OBoos::Spawn(5, IPathSpan(490, 500), IPathSpan(510, 520), IPathSpan(620, 630));
SpawnActor<OBat>(FVector(0,0,0), IRotator(0, 0, 90));
SpawnActor<OBoos>(5, IPathSpan(180, 190), IPathSpan(200, 210), IPathSpan(280, 290));
SpawnActor<OBoos>(5, IPathSpan(490, 500), IPathSpan(510, 520), IPathSpan(620, 630));
}
if (gModeSelection == VERSUS) {
OBombKart::Spawn(0, 110, 3, 0.8333333f);
OBombKart::Spawn(0, 190, 1, 0.8333333f);
OBombKart::Spawn(0, 250, 3, 0.8333333f);
OBombKart::Spawn(0, 475, 1, 0.8333333f);
OBombKart::Spawn(0, 610, 3, 0.8333333f);
OBombKart::Spawn(0, 0, 0, 0.8333333f);
OBombKart::Spawn(0, 0, 0, 0.8333333f);
SpawnActor<OBombKart>(0, 110, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 190, 1, 0.8333333f);
SpawnActor<OBombKart>(0, 250, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 475, 1, 0.8333333f);
SpawnActor<OBombKart>(0, 610, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 0, 0, 0.8333333f);
SpawnActor<OBombKart>(0, 0, 0, 0.8333333f);
}
}
@ -259,7 +257,7 @@ void BansheeBoardwalk::Draw(ScreenContext* arg0) {
// d_course_banshee_boardwalk_packed_dl_7228
gSPDisplayList(gDisplayListHead++, (Gfx*) d_course_banshee_boardwalk_packed_dl_7228);
gSPFogPosition(gDisplayListHead++, D_802B87B0, D_802B87B4);
gSPFogPosition(gDisplayListHead++, gFogMin, gFogMax);
gDPPipeSync(gDisplayListHead++);

View File

@ -18,15 +18,12 @@ extern "C" {
class BansheeBoardwalk : public Track {
public:
virtual ~BansheeBoardwalk() = default; // Virtual destructor for proper cleanup in derived classes
// Constructor
explicit BansheeBoardwalk();
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void UnLoad() override;
virtual void BeginPlay() override;
//virtual void InitClouds() override;
virtual void InitTrackObjects() override;

View File

@ -125,20 +125,17 @@ void BigDonut::Load() {
func_80295C6C();
}
void BigDonut::UnLoad() {
}
void BigDonut::BeginPlay() {
spawn_all_item_boxes((ActorSpawnData*) LOAD_ASSET_RAW(d_course_big_donut_item_box_spawns));
if (gModeSelection == VERSUS) {
OBombKart::Spawn(0, 20, 0, 1.0f);
OBombKart::Spawn(0, 40, 0, 1.0f);
OBombKart::Spawn(0, 60, 0, 1.0f);
OBombKart::Spawn(0, 80, 0, 1.0f);
OBombKart::Spawn(0, 100, 0, 1.0f);
OBombKart::Spawn(0, 120, 0, 1.0);
OBombKart::Spawn(0, 140, 0, 1.0f);
SpawnActor<OBombKart>(0, 20, 0, 1.0f);
SpawnActor<OBombKart>(0, 40, 0, 1.0f);
SpawnActor<OBombKart>(0, 60, 0, 1.0f);
SpawnActor<OBombKart>(0, 80, 0, 1.0f);
SpawnActor<OBombKart>(0, 100, 0, 1.0f);
SpawnActor<OBombKart>(0, 120, 0, 1.0);
SpawnActor<OBombKart>(0, 140, 0, 1.0f);
}
}

View File

@ -18,12 +18,9 @@ extern "C" {
class BigDonut : public Track {
public:
virtual ~BigDonut() = default;
explicit BigDonut();
virtual void Load() override;
virtual void UnLoad() override;
virtual void BeginPlay() override;
virtual void Draw(ScreenContext*) override;
virtual void DrawCredits() override;

View File

@ -116,20 +116,17 @@ void BlockFort::Load() {
Props.WaterLevel = gTrackMinY - 10.0f;
}
void BlockFort::UnLoad() {
}
void BlockFort::BeginPlay() {
spawn_all_item_boxes((ActorSpawnData*) LOAD_ASSET_RAW(d_course_block_fort_item_box_spawns));
if (gModeSelection == VERSUS) {
OBombKart::Spawn(0, 20, 0, 1.0f);
OBombKart::Spawn(0, 40, 0, 1.0f);
OBombKart::Spawn(0, 60, 0, 1.0f);
OBombKart::Spawn(0, 80, 0, 1.0f);
OBombKart::Spawn(0, 100, 0, 1.0f);
OBombKart::Spawn(0, 120, 0, 1.0f);
OBombKart::Spawn(0, 140, 0, 1.0f);
SpawnActor<OBombKart>(0, 20, 0, 1.0f);
SpawnActor<OBombKart>(0, 40, 0, 1.0f);
SpawnActor<OBombKart>(0, 60, 0, 1.0f);
SpawnActor<OBombKart>(0, 80, 0, 1.0f);
SpawnActor<OBombKart>(0, 100, 0, 1.0f);
SpawnActor<OBombKart>(0, 120, 0, 1.0f);
SpawnActor<OBombKart>(0, 140, 0, 1.0f);
}
}

View File

@ -18,15 +18,12 @@ extern "C" {
class BlockFort : public Track {
public:
virtual ~BlockFort() = default; // Virtual destructor for proper cleanup in derived classes
// Constructor
explicit BlockFort();
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void UnLoad() override;
virtual void BeginPlay() override;
virtual void Draw(ScreenContext*) override;
virtual void Waypoints(Player*, int8_t) override;

View File

@ -50,7 +50,7 @@ BowsersCastle::BowsersCastle() {
Props.Minimap.FinishlineY = 0;
ResizeMinimap(&Props.Minimap);
Id = "mk:bowsers_castle";
ResourceName = "mk:bowsers_castle";
Props.SetText(Props.Name, "bowser's castle", sizeof(Props.Name));
Props.SetText(Props.DebugName, "castle", sizeof(Props.DebugName));
@ -131,10 +131,6 @@ void BowsersCastle::Load() {
find_vtx_and_set_colours((Gfx*) d_course_bowsers_castle_packed_dl_1350, 0x32, 0, 0, 0);
}
void BowsersCastle::UnLoad() {
RestoreTriangleWinding();
}
void BowsersCastle::BeginPlay() {
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));
@ -142,52 +138,52 @@ void BowsersCastle::BeginPlay() {
switch (gCCSelection) {
case CC_100:
case CC_EXTRA:
OThwomp::Spawn(0x0320, 0xf92a, 0xC000, 1.0f, OThwomp::States::STATIONARY, 0);
OThwomp::Spawn(0x044c, 0xf92a, 0xC000, 1.0f, OThwomp::States::STATIONARY, 1);
OThwomp::Spawn(0x02bc, 0xf95c, 0xC000, 1.0f, OThwomp::States::MOVE_AND_ROTATE, 0);
OThwomp::Spawn(0x04b0, 0xf8f8, 0xC000, 1.0f, OThwomp::States::MOVE_AND_ROTATE, 1);
OThwomp::Spawn(0x04b0, 0xf5ba, 0xC000, 1.0f, OThwomp::States::MOVE_FAR, 0);
OThwomp::Spawn(0x04b0, 0xf592, 0xC000, 1.0f, OThwomp::States::MOVE_FAR, 1);
OThwomp::Spawn(0x091a, 0xf5bf, 0xC000, 1.0f, OThwomp::States::STATIONARY_FAST, 0);
OThwomp::Spawn(0x091a, 0xf597, 0xC000, 1.0f, OThwomp::States::STATIONARY_FAST, 1);
OThwomp::Spawn(0x0596, 0xf92f, 0xC000, 1.5f, OThwomp::States::JAILED, 0);
OThwomp::Spawn(0x082a, 0xf9f2, 0x4000, 1.0f, OThwomp::States::SLIDE, 0);
OThwomp::Spawn(0x073a, 0xf9f2, 0x4000, 1.0f, OThwomp::States::SLIDE, 1);
SpawnActor<OThwomp>(0x0320, 0xf92a, 0xC000, 1.0f, OThwomp::States::STATIONARY, 0);
SpawnActor<OThwomp>(0x044c, 0xf92a, 0xC000, 1.0f, OThwomp::States::STATIONARY, 1);
SpawnActor<OThwomp>(0x02bc, 0xf95c, 0xC000, 1.0f, OThwomp::States::MOVE_AND_ROTATE, 0);
SpawnActor<OThwomp>(0x04b0, 0xf8f8, 0xC000, 1.0f, OThwomp::States::MOVE_AND_ROTATE, 1);
SpawnActor<OThwomp>(0x04b0, 0xf5ba, 0xC000, 1.0f, OThwomp::States::MOVE_FAR, 0);
SpawnActor<OThwomp>(0x04b0, 0xf592, 0xC000, 1.0f, OThwomp::States::MOVE_FAR, 1);
SpawnActor<OThwomp>(0x091a, 0xf5bf, 0xC000, 1.0f, OThwomp::States::STATIONARY_FAST, 0);
SpawnActor<OThwomp>(0x091a, 0xf597, 0xC000, 1.0f, OThwomp::States::STATIONARY_FAST, 1);
SpawnActor<OThwomp>(0x0596, 0xf92f, 0xC000, 1.5f, OThwomp::States::JAILED, 0);
SpawnActor<OThwomp>(0x082a, 0xf9f2, 0x4000, 1.0f, OThwomp::States::SLIDE, 0);
SpawnActor<OThwomp>(0x073a, 0xf9f2, 0x4000, 1.0f, OThwomp::States::SLIDE, 1);
break;
case CC_50:
OThwomp::Spawn(0x3B6, 0xF92A, 0xC000, 1.0f, OThwomp::States::STATIONARY, 0);
OThwomp::Spawn(0x0352, 0xf95c, 0xC000, 1.0f, OThwomp::States::MOVE_AND_ROTATE, 0);
OThwomp::Spawn(0x04b0, 0xf5ba, 0xC000, 1.0f, OThwomp::States::MOVE_FAR, 0);
OThwomp::Spawn(0x04b0, 0xf592, 0xC000, 1.0f, OThwomp::States::MOVE_FAR, 1);
OThwomp::Spawn(0x091a, 0xf5b0, 0xC000, 1.0f, OThwomp::States::STATIONARY_FAST, 0);
OThwomp::Spawn(0x0596, 0xf92f, 0xC000, 1.5f, OThwomp::States::JAILED, 0);
OThwomp::Spawn(0x082a, 0xf9f2, 0x4000, 1.0f, OThwomp::States::SLIDE , 0);
OThwomp::Spawn(0x073a, 0xf9f2, 0x4000, 1.0f, OThwomp::States::SLIDE, 1);
SpawnActor<OThwomp>(0x3B6, 0xF92A, 0xC000, 1.0f, OThwomp::States::STATIONARY, 0);
SpawnActor<OThwomp>(0x0352, 0xf95c, 0xC000, 1.0f, OThwomp::States::MOVE_AND_ROTATE, 0);
SpawnActor<OThwomp>(0x04b0, 0xf5ba, 0xC000, 1.0f, OThwomp::States::MOVE_FAR, 0);
SpawnActor<OThwomp>(0x04b0, 0xf592, 0xC000, 1.0f, OThwomp::States::MOVE_FAR, 1);
SpawnActor<OThwomp>(0x091a, 0xf5b0, 0xC000, 1.0f, OThwomp::States::STATIONARY_FAST, 0);
SpawnActor<OThwomp>(0x0596, 0xf92f, 0xC000, 1.5f, OThwomp::States::JAILED, 0);
SpawnActor<OThwomp>(0x082a, 0xf9f2, 0x4000, 1.0f, OThwomp::States::SLIDE , 0);
SpawnActor<OThwomp>(0x073a, 0xf9f2, 0x4000, 1.0f, OThwomp::States::SLIDE, 1);
break;
case CC_150:
OThwomp::Spawn(0x0320, 0xf92a, 0xC000, 1.0f, OThwomp::States::STATIONARY, 0);
OThwomp::Spawn(0x044c, 0xf92a, 0xC000, 1.0f, OThwomp::States::STATIONARY, 1);
OThwomp::Spawn(0x02bc, 0xf95c, 0xC000, 1.0f, OThwomp::States::MOVE_AND_ROTATE, 0);
OThwomp::Spawn(0x04b0, 0xf8f8, 0xC000, 1.0f, OThwomp::States::MOVE_AND_ROTATE, 1);
OThwomp::Spawn(0x04b0, 0xf5ba, 0xC000, 1.0f, OThwomp::States::MOVE_FAR, 0);
OThwomp::Spawn(0x04b0, 0xf592, 0xC000, 1.0f, OThwomp::States::MOVE_FAR, 1);
OThwomp::Spawn(0x091a, 0xf5c9, 0xC000, 1.0f, OThwomp::States::STATIONARY_FAST, 0);
OThwomp::Spawn(0x091a, 0xf5ab, 0xC000, 1.0f, OThwomp::States::STATIONARY_FAST, 1);
OThwomp::Spawn(0x091a, 0xf58d, 0xC000, 1.0f, OThwomp::States::STATIONARY_FAST, 2);
OThwomp::Spawn(0x0596, 0xf92f, 0xC000, 1.5f, OThwomp::States::JAILED, 0);
OThwomp::Spawn(0x082a, 0xf9f2, 0x4000, 1.0f, OThwomp::States::SLIDE, 0);
OThwomp::Spawn(0x073a, 0xf9f2, 0x4000, 1.0f, OThwomp::States::SLIDE, 1);
SpawnActor<OThwomp>(0x0320, 0xf92a, 0xC000, 1.0f, OThwomp::States::STATIONARY, 0);
SpawnActor<OThwomp>(0x044c, 0xf92a, 0xC000, 1.0f, OThwomp::States::STATIONARY, 1);
SpawnActor<OThwomp>(0x02bc, 0xf95c, 0xC000, 1.0f, OThwomp::States::MOVE_AND_ROTATE, 0);
SpawnActor<OThwomp>(0x04b0, 0xf8f8, 0xC000, 1.0f, OThwomp::States::MOVE_AND_ROTATE, 1);
SpawnActor<OThwomp>(0x04b0, 0xf5ba, 0xC000, 1.0f, OThwomp::States::MOVE_FAR, 0);
SpawnActor<OThwomp>(0x04b0, 0xf592, 0xC000, 1.0f, OThwomp::States::MOVE_FAR, 1);
SpawnActor<OThwomp>(0x091a, 0xf5c9, 0xC000, 1.0f, OThwomp::States::STATIONARY_FAST, 0);
SpawnActor<OThwomp>(0x091a, 0xf5ab, 0xC000, 1.0f, OThwomp::States::STATIONARY_FAST, 1);
SpawnActor<OThwomp>(0x091a, 0xf58d, 0xC000, 1.0f, OThwomp::States::STATIONARY_FAST, 2);
SpawnActor<OThwomp>(0x0596, 0xf92f, 0xC000, 1.5f, OThwomp::States::JAILED, 0);
SpawnActor<OThwomp>(0x082a, 0xf9f2, 0x4000, 1.0f, OThwomp::States::SLIDE, 0);
SpawnActor<OThwomp>(0x073a, 0xf9f2, 0x4000, 1.0f, OThwomp::States::SLIDE, 1);
break;
}
if (gModeSelection == VERSUS) {
OBombKart::Spawn(0, 50, 3, 0.8333333f);
OBombKart::Spawn(0, 150, 1, 0.8333333f);
OBombKart::Spawn(0, 200, 3, 0.8333333f);
OBombKart::Spawn(0, 260, 1, 0.8333333f);
OBombKart::Spawn(0, 435, 3, 0.8333333f);
OBombKart::Spawn(0, 0, 0, 0.8333333f);
OBombKart::Spawn(0, 0, 0, 0.8333333f);
SpawnActor<OBombKart>(0, 50, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 150, 1, 0.8333333f);
SpawnActor<OBombKart>(0, 200, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 260, 1, 0.8333333f);
SpawnActor<OBombKart>(0, 435, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 0, 0, 0.8333333f);
SpawnActor<OBombKart>(0, 0, 0, 0.8333333f);
}
}

View File

@ -18,15 +18,12 @@ extern "C" {
class BowsersCastle : public Track {
public:
virtual ~BowsersCastle() = default; // Virtual destructor for proper cleanup in derived classes
// Constructor
explicit BowsersCastle();
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void UnLoad() override;
void SpawnStockThwomp();
virtual void BeginPlay() override;
//virtual void InitClouds() override;

View File

@ -50,7 +50,7 @@ ChocoMountain::ChocoMountain() {
Props.Minimap.FinishlineY = -16.0;
ResizeMinimap(&Props.Minimap);
Id = "mk:choco_mountain";
ResourceName = "mk:choco_mountain";
Props.SetText(Props.Name, "choco mountain", sizeof(Props.Name));
Props.SetText(Props.DebugName, "mountain", sizeof(Props.DebugName));
Props.SetText(Props.TrackLength, "687m", sizeof(Props.TrackLength));
@ -127,12 +127,13 @@ void ChocoMountain::Load() {
InvertTriangleWindingByName(d_course_choco_mountain_packed_dl_5D8);
InvertTriangleWindingByName(d_course_choco_mountain_packed_dl_718);
}
D_800DC5BC = 1;
D_801625EC = 255;
D_801625F4 = 255;
D_801625F0 = 255;
D_802B87B0 = 0x3E3;
D_802B87B4 = 0x3E8;
bFog = true;
gFogColour.r = 255;
gFogColour.g = 255;
gFogColour.b = 255;
gFogColour.a = 255;
gFogMin = 0x3E3;
gFogMax = 0x3E8;
D_802B87D4 = 0x71C;
D_802B87D0 = 0xE38;
@ -157,24 +158,20 @@ void ChocoMountain::Load() {
func_80295C6C();
}
void ChocoMountain::UnLoad() {
RestoreTriangleWinding();
}
void ChocoMountain::BeginPlay() {
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_choco_mountain_item_box_spawns));
AFallingRock::Spawn(FVector(2019, 156, 164), 60);
AFallingRock::Spawn(FVector(2018, 155, 379), 120);
AFallingRock::Spawn(FVector(1996, 146, 505), 180);
SpawnActor<AFallingRock>(FVector(2019, 156, 164), 60);
SpawnActor<AFallingRock>(FVector(2018, 155, 379), 120);
SpawnActor<AFallingRock>(FVector(1996, 146, 505), 180);
if (gModeSelection == VERSUS) {
OBombKart::Spawn(0, 140, 3, 0.8333333f);
OBombKart::Spawn(0, 165, 1, 0.8333333f);
OBombKart::Spawn(0, 330, 3, 0.8333333f);
OBombKart::Spawn(0, 550, 1, 0.8333333f);
OBombKart::Spawn(0, 595, 3, 0.8333333f);
OBombKart::Spawn(0, 0, 0, 0.8333333f);
OBombKart::Spawn(0, 0, 0, 0.8333333f);
SpawnActor<OBombKart>(0, 140, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 165, 1, 0.8333333f);
SpawnActor<OBombKart>(0, 330, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 550, 1, 0.8333333f);
SpawnActor<OBombKart>(0, 595, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 0, 0, 0.8333333f);
SpawnActor<OBombKart>(0, 0, 0, 0.8333333f);
}
}
@ -236,8 +233,8 @@ void ChocoMountain::Draw(ScreenContext* arg0) {
gSPDisplayList(gDisplayListHead++, (Gfx*) d_course_choco_mountain_packed_dl_4608);
}
gDPSetCycleType(gDisplayListHead++, G_CYC_2CYCLE);
gDPSetFogColor(gDisplayListHead++, D_801625EC, D_801625F4, D_801625F0, 0xFF);
gSPFogPosition(gDisplayListHead++, D_802B87B0, D_802B87B4);
gDPSetFogColor(gDisplayListHead++, gFogColour.r, gFogColour.g, gFogColour.b, gFogColour.a);
gSPFogPosition(gDisplayListHead++, gFogMin, gFogMax);
gDPPipeSync(gDisplayListHead++);
gSPSetGeometryMode(gDisplayListHead++, G_FOG);

View File

@ -18,15 +18,12 @@ extern "C" {
class ChocoMountain : public Track {
public:
virtual ~ChocoMountain() = default; // Virtual destructor for proper cleanup in derived classes
// Constructor
explicit ChocoMountain();
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void UnLoad() override;
virtual void BeginPlay() override;
virtual void InitTrackObjects() override;
virtual void SomeSounds() override;

View File

@ -133,10 +133,6 @@ void DKJungle::Load() {
find_vtx_and_set_colours((Gfx*) d_course_dks_jungle_parkway_packed_dl_3FA8, 120, 255, 255, 255);
}
void DKJungle::UnLoad() {
RestoreTriangleWinding();
}
f32 DKJungle::GetWaterLevel(FVector pos, Collision* collision) {
int32_t temp_v1 = get_track_section_id(collision->meshIndexZX) & 0xFF;
@ -179,16 +175,16 @@ void DKJungle::BeginPlay() {
// The original game only ran vehicle logic every second frame.
// Thus the speed gets divided by two to set speed to match properly
ABoat::Spawn((0.6666666f)/4, 0, 0, ABoat::SpawnMode::POINT);
SpawnActor<ABoat>((0.6666666f)/4, 0, 0, ABoat::SpawnMode::POINT);
if (gModeSelection == VERSUS) {
OBombKart::Spawn(0, 50, 3, 0.8333333f);
OBombKart::Spawn(0, 100, 1, 0.8333333f);
OBombKart::Spawn(0, 150, 3, 0.8333333f);
OBombKart::Spawn(0, 190, 1, 0.8333333f);
OBombKart::Spawn(0, 250, 3, 0.8333333f);
OBombKart::Spawn(0, 0, 0, 0.8333333f);
OBombKart::Spawn(0, 0, 0, 0.8333333f);
SpawnActor<OBombKart>(0, 50, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 100, 1, 0.8333333f);
SpawnActor<OBombKart>(0, 150, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 190, 1, 0.8333333f);
SpawnActor<OBombKart>(0, 250, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 0, 0, 0.8333333f);
SpawnActor<OBombKart>(0, 0, 0, 0.8333333f);
}
}
}

View File

@ -18,15 +18,12 @@ extern "C" {
class DKJungle : public Track {
public:
virtual ~DKJungle() = default; // Virtual destructor for proper cleanup in derived classes
// Constructor
explicit DKJungle();
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void UnLoad() override;
virtual f32 GetWaterLevel(FVector pos, Collision* collision) override;
virtual void BeginPlay() override;
//virtual void InitClouds() override;

View File

@ -115,20 +115,17 @@ void DoubleDeck::Load() {
Props.WaterLevel = gTrackMinY - 10.0f;
}
void DoubleDeck::UnLoad() {
}
void DoubleDeck::BeginPlay() {
spawn_all_item_boxes((ActorSpawnData*)LOAD_ASSET_RAW(d_course_double_deck_item_box_spawns));
if (gModeSelection == VERSUS) {
OBombKart::Spawn(0, 20, 0, 1.0f);
OBombKart::Spawn(0, 40, 0, 1.0f);
OBombKart::Spawn(0, 60, 0, 1.0f);
OBombKart::Spawn(0, 80, 0, 1.0f);
OBombKart::Spawn(0, 100, 0, 1.0f);
OBombKart::Spawn(0, 120, 0, 1.0f);
OBombKart::Spawn(0, 140, 0, 1.0f);
SpawnActor<OBombKart>(0, 20, 0, 1.0f);
SpawnActor<OBombKart>(0, 40, 0, 1.0f);
SpawnActor<OBombKart>(0, 60, 0, 1.0f);
SpawnActor<OBombKart>(0, 80, 0, 1.0f);
SpawnActor<OBombKart>(0, 100, 0, 1.0f);
SpawnActor<OBombKart>(0, 120, 0, 1.0f);
SpawnActor<OBombKart>(0, 140, 0, 1.0f);
}
}

View File

@ -18,15 +18,12 @@ extern "C" {
class DoubleDeck : public Track {
public:
virtual ~DoubleDeck() = default; // Virtual destructor for proper cleanup in derived classes
// Constructor
explicit DoubleDeck();
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void UnLoad() override;
virtual void BeginPlay() override;
virtual void InitTrackObjects() override;
virtual void SomeSounds() override;

View File

@ -127,44 +127,40 @@ void FrappeSnowland::Load() {
func_80295C6C();
}
void FrappeSnowland::UnLoad() {
RestoreTriangleWinding();
}
void FrappeSnowland::BeginPlay() {
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_frappe_snowland_tree_spawns));
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_frappe_snowland_item_box_spawns));
if (gGamestate != CREDITS_SEQUENCE) {
OSnowman::Spawn(FVector(697, 0, -1684));
OSnowman::Spawn(FVector(82, 0, -2245));
OSnowman::Spawn(FVector(27, 5, -2067));
OSnowman::Spawn(FVector(-656, 0, -1735));
OSnowman::Spawn(FVector(-1497, 0, -83));
OSnowman::Spawn(FVector(-1643, 0, -25));
OSnowman::Spawn(FVector(-1547, 0, -20));
OSnowman::Spawn(FVector(-1445, 0, -10));
OSnowman::Spawn(FVector(-1502, 0, 61));
OSnowman::Spawn(FVector(-1429, 0, 79));
OSnowman::Spawn(FVector(-1586, 0, 71));
OSnowman::Spawn(FVector(-1471, 0, 157));
OSnowman::Spawn(FVector(-1539, 0, 175));
OSnowman::Spawn(FVector(-1484, 0, 303));
OSnowman::Spawn(FVector(-1442, 0, 358));
OSnowman::Spawn(FVector(-1510, 0, 426));
OSnowman::Spawn(FVector(-665, 0, 830));
OSnowman::Spawn(FVector(-701, 3, 853));
OSnowman::Spawn(FVector(-602, 0, 929));
SpawnActor<OSnowman>(FVector(697, 0, -1684));
SpawnActor<OSnowman>(FVector(82, 0, -2245));
SpawnActor<OSnowman>(FVector(27, 5, -2067));
SpawnActor<OSnowman>(FVector(-656, 0, -1735));
SpawnActor<OSnowman>(FVector(-1497, 0, -83));
SpawnActor<OSnowman>(FVector(-1643, 0, -25));
SpawnActor<OSnowman>(FVector(-1547, 0, -20));
SpawnActor<OSnowman>(FVector(-1445, 0, -10));
SpawnActor<OSnowman>(FVector(-1502, 0, 61));
SpawnActor<OSnowman>(FVector(-1429, 0, 79));
SpawnActor<OSnowman>(FVector(-1586, 0, 71));
SpawnActor<OSnowman>(FVector(-1471, 0, 157));
SpawnActor<OSnowman>(FVector(-1539, 0, 175));
SpawnActor<OSnowman>(FVector(-1484, 0, 303));
SpawnActor<OSnowman>(FVector(-1442, 0, 358));
SpawnActor<OSnowman>(FVector(-1510, 0, 426));
SpawnActor<OSnowman>(FVector(-665, 0, 830));
SpawnActor<OSnowman>(FVector(-701, 3, 853));
SpawnActor<OSnowman>(FVector(-602, 0, 929));
}
if (gModeSelection == VERSUS) {
OBombKart::Spawn(0, 50, 3, 0.8333333f);
OBombKart::Spawn(0, 100, 1, 0.8333333f);
OBombKart::Spawn(0, 150, 3, 0.8333333f);
OBombKart::Spawn(0, 290, 1, 0.8333333f);
OBombKart::Spawn(0, 350, 3, 0.8333333f);
OBombKart::Spawn(0, 0, 0, 0.8333333f);
OBombKart::Spawn(0, 0, 0, 0.8333333f);
SpawnActor<OBombKart>(0, 50, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 100, 1, 0.8333333f);
SpawnActor<OBombKart>(0, 150, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 290, 1, 0.8333333f);
SpawnActor<OBombKart>(0, 350, 3, 0.8333333f);
SpawnActor<OBombKart>(0, 0, 0, 0.8333333f);
SpawnActor<OBombKart>(0, 0, 0, 0.8333333f);
}
}

View File

@ -18,12 +18,9 @@ extern "C" {
class FrappeSnowland : public Track {
public:
virtual ~FrappeSnowland() = default;
explicit FrappeSnowland();
virtual void Load() override;
virtual void UnLoad() override;
virtual void BeginPlay() override;
virtual void InitClouds() override;
virtual void TickClouds(s32 sp1C, Camera* camera) override;

View File

@ -526,7 +526,7 @@ Harbour::Harbour() {
Props.Minimap.PlayerScaleFactor = 0.022f;
ResizeMinimap(&Props.Minimap);
Id = "mk:harbour";
ResourceName = "mk:harbour";
Props.SetText(Props.Name, "Harbour", sizeof(Props.Name));
Props.SetText(Props.DebugName, "harbour", sizeof(Props.DebugName));
Props.SetText(Props.TrackLength, "99m", sizeof(Props.TrackLength));
@ -626,9 +626,6 @@ void Harbour::Load() {
Props.WaterLevel = gTrackMinY - 10.0f;
}
void Harbour::UnLoad() {
}
void Harbour::BeginPlay() {
struct ActorSpawnData itemboxes[] = {
{ 200, 1500, 200 , 0},
@ -662,28 +659,28 @@ void Harbour::BeginPlay() {
Vec3f pos = {0, 80, 0};
// gWorldInstance.AddActor(new ACloud(pos));
// GetWorld()->AddActor(new ACloud(pos));
// gWorldInstance.AddActor(new OSeagull(0, pos));
// gWorldInstance.AddActor(new OSeagull(1, pos));
// gWorldInstance.AddActor(new OSeagull(2, pos));
// gWorldInstance.AddActor(new OSeagull(3, pos));
// gWorldInstance.AddObject(new OCheepCheep(FVector(0, 40, 0), OCheepCheep::CheepType::RACE, IPathSpan(0, 10)));
// gWorldInstance.AddObject(new OTrophy(FVector(0,0,0), OTrophy::TrophyType::GOLD, OTrophy::Behaviour::GO_FISH));
//gWorldInstance.AddObject(new OSnowman(FVector(0, 0, 0)));
//gWorldInstance.AddObject(new OTrashBin(FVector(0.0f, 0.0f, 0.0f), IRotator(0, 90, 0), 1.0f, OTrashBin::Behaviour::MUNCHING));
// GetWorld()->AddActor(new OSeagull(0, pos));
// GetWorld()->AddActor(new OSeagull(1, pos));
// GetWorld()->AddActor(new OSeagull(2, pos));
// GetWorld()->AddActor(new OSeagull(3, pos));
// GetWorld()->AddObject(new OCheepCheep(FVector(0, 40, 0), OCheepCheep::CheepType::RACE, IPathSpan(0, 10)));
// GetWorld()->AddObject(new OTrophy(FVector(0,0,0), OTrophy::TrophyType::GOLD, OTrophy::Behaviour::GO_FISH));
//GetWorld()->AddObject(new OSnowman(FVector(0, 0, 0)));
//GetWorld()->AddObject(new OTrashBin(FVector(0.0f, 0.0f, 0.0f), IRotator(0, 90, 0), 1.0f, OTrashBin::Behaviour::MUNCHING));
//gWorldInstance.AddObject(new OHedgehog(FVector(0, 0, 0), FVector2D(0, -200), 9));
//gWorldInstance.AddObject(new OFlagpole(FVector(0, 0, -200), 0x400));
// gWorldInstance.AddObject(new OHotAirBalloon(FVector(0.0, 20.0f, -200.0f)));
//GetWorld()->AddObject(new OHedgehog(FVector(0, 0, 0), FVector2D(0, -200), 9));
//GetWorld()->AddObject(new OFlagpole(FVector(0, 0, -200), 0x400));
// GetWorld()->AddObject(new OHotAirBalloon(FVector(0.0, 20.0f, -200.0f)));
//gWorldInstance.AddObject(new OCrab(FVector2D(0, 0), FVector2D(0, -200)));
// gWorldInstance.AddActor(new ABowserStatue(FVector(-200, 0, 0), ABowserStatue::Behaviour::CRUSH));
//GetWorld()->AddObject(new OCrab(FVector2D(0, 0), FVector2D(0, -200)));
// GetWorld()->AddActor(new ABowserStatue(FVector(-200, 0, 0), ABowserStatue::Behaviour::CRUSH));
// gWorldInstance.AddObject(new OBoos(10, IPathSpan(0, 5), IPathSpan(18, 23), IPathSpan(25, 50)));
// GetWorld()->AddObject(new OBoos(10, IPathSpan(0, 5), IPathSpan(18, 23), IPathSpan(25, 50)));
//gWorldInstance.AddActor(new AShip(FVector(-1694, -111, 1451), AShip::Skin::GHOSTSHIP));
//gWorldInstance.AddActor(new AShip(FVector(2811, -83, 966), AShip::Skin::SHIP2));
//GetWorld()->AddActor(new AShip(FVector(-1694, -111, 1451), AShip::Skin::GHOSTSHIP));
//GetWorld()->AddActor(new AShip(FVector(2811, -83, 966), AShip::Skin::SHIP2));
}
void Harbour::WhatDoesThisDo(Player* player, int8_t playerId) {

View File

@ -16,15 +16,12 @@ extern "C" {
class Harbour : public Track {
public:
virtual ~Harbour() = default; // Virtual destructor for proper cleanup in derived classes
// Constructor
explicit Harbour();
// virtual void Load(const char* courseVtx,
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void UnLoad() override;
virtual void BeginPlay() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;

Some files were not shown because too many files have changed in this diff Show More