RaceManager class (#562)
* Create RaceManager.cpp * Create RaceManager class for race lifecycle management Added RaceManager class to manage race events lifecycle. * Refactor World class and implement ClearWorld method Refactor World class constructor and destructor. Implement ClearWorld method to delete all objects and reset state. * Add RaceManager to World class * Update ValidateString for editor mode checks Refactor ValidateString to handle editor mode and empty strings. * Update Text.cpp * Add SetText method to Text class * Document RunGarbageCollector function Added documentation for the RunGarbageCollector function. * Refactor Game.cpp by removing dead code Removed unused ruleset handling and clean-up code. * Update Game.h * Remove CM_SpawnFromLevelProps call * Update Text.cpp * Update World.cpp * Add Clean method to RaceManager class * Update RaceManager.cpp * Update World.cpp * Update World.h * Update World.cpp
This commit is contained in:
parent
c2755aee40
commit
fffd3f7fe9
|
|
@ -1,6 +1,9 @@
|
|||
#include "GarbageCollector.h"
|
||||
#include "World.h"
|
||||
|
||||
/**
|
||||
* Removes objects if they are marked for deletion
|
||||
*/
|
||||
void RunGarbageCollector() {
|
||||
CleanActors();
|
||||
CleanObjects();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
#include "RaceManager.h"
|
||||
|
||||
#include "AllActors.h"
|
||||
#include "World.h"
|
||||
#include "port/Game.h"
|
||||
#include "engine/editor/Editor.h"
|
||||
#include "engine/editor/SceneManager.h"
|
||||
|
||||
extern "C" {
|
||||
#include "render_courses.h"
|
||||
}
|
||||
|
||||
RaceManager::RaceManager(World& world) : WorldContext(world) {
|
||||
}
|
||||
|
||||
void RaceManager::Load() {
|
||||
if (WorldContext.CurrentCourse) {
|
||||
WorldContext.CurrentCourse->Load();
|
||||
}
|
||||
}
|
||||
|
||||
void RaceManager::PreInit() {
|
||||
// Ruleset options
|
||||
if (CVarGetInteger("gDisableItemboxes", false) == true) {
|
||||
gPlaceItemBoxes = false;
|
||||
} else {
|
||||
gPlaceItemBoxes = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RaceManager::BeginPlay() {
|
||||
auto course = WorldContext.CurrentCourse;
|
||||
|
||||
if (course) {
|
||||
// Do not spawn finishline in credits or battle mode. And if bSpawnFinishline.
|
||||
if ((gGamestate != CREDITS_SEQUENCE) && (gModeSelection != BATTLE)) {
|
||||
if (course->bSpawnFinishline) {
|
||||
if (course->FinishlineSpawnPoint.has_value()) {
|
||||
AFinishline::Spawn(course->FinishlineSpawnPoint.value(), IRotator(0, 0, 0));
|
||||
} else {
|
||||
AFinishline::Spawn();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
gEditor.AddLight("Sun", nullptr, D_800DC610[1].l->l.dir);
|
||||
|
||||
course->BeginPlay();
|
||||
}
|
||||
}
|
||||
|
||||
void RaceManager::PostInit() {
|
||||
// Ruleset options
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void RaceManager::Clean() {
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
class World;
|
||||
|
||||
/**
|
||||
* This may eventually become GameMode class
|
||||
*
|
||||
* The RaceManager orchestrates the event lifecycle
|
||||
* It defines when a race begins, actors spawn, and the race ends.
|
||||
*
|
||||
* It does not define the game mode itself.
|
||||
*
|
||||
* You must call the base function if you want the
|
||||
* default functionality to run
|
||||
* Example:
|
||||
* MyRaceManager::BeginPlay() {
|
||||
* RaceManager::BeginPlay() // <-- Calls default functionality
|
||||
* // My code here
|
||||
* }
|
||||
*/
|
||||
class RaceManager {
|
||||
public:
|
||||
RaceManager(World& world);
|
||||
virtual void Load(); // virtual required here in the base class to allow inherited classes to override
|
||||
virtual void PreInit();
|
||||
virtual void BeginPlay();
|
||||
virtual void PostInit();
|
||||
virtual void Clean();
|
||||
protected:
|
||||
World& WorldContext;
|
||||
};
|
||||
|
|
@ -21,14 +21,17 @@ extern "C" {
|
|||
#include "mario_raceway_data.h"
|
||||
}
|
||||
|
||||
World::World() {}
|
||||
World::~World() {
|
||||
CM_CleanWorld();
|
||||
}
|
||||
|
||||
std::shared_ptr<Course> CurrentCourse;
|
||||
Cup* CurrentCup;
|
||||
|
||||
World::World() {
|
||||
RaceManagerInstance = std::make_unique<RaceManager>(*this);
|
||||
}
|
||||
|
||||
World::~World() {
|
||||
ClearWorld();
|
||||
}
|
||||
|
||||
std::shared_ptr<Course> World::AddCourse(std::shared_ptr<Course> course) {
|
||||
gWorldInstance.Courses.push_back(course);
|
||||
return course;
|
||||
|
|
@ -252,13 +255,39 @@ Object* World::GetObjectByIndex(size_t index) {
|
|||
return nullptr; // Or handle the error as needed
|
||||
}
|
||||
|
||||
// Deletes all objects from the world
|
||||
void World::ClearWorld(void) {
|
||||
CM_CleanWorld();
|
||||
printf("[Game.cpp] Clean World\n");
|
||||
World* world = &gWorldInstance;
|
||||
for (auto& actor : world->Actors) {
|
||||
delete actor;
|
||||
}
|
||||
|
||||
// for (size_t i = 0; i < ARRAY_COUNT(gCollisionMesh); i++) {
|
||||
gWorldInstance.Reset(); // Reset OObjects
|
||||
for (auto& object : world->Objects) {
|
||||
delete object;
|
||||
}
|
||||
|
||||
// }
|
||||
for (auto& emitter : world->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;
|
||||
}
|
||||
|
||||
gEditor.ClearObjects();
|
||||
gWorldInstance.Actors.clear();
|
||||
gWorldInstance.StaticMeshActors.clear();
|
||||
gWorldInstance.Objects.clear();
|
||||
gWorldInstance.Emitters.clear();
|
||||
gWorldInstance.Lakitus.clear();
|
||||
|
||||
gWorldInstance.GetRaceManager().Clean();
|
||||
|
||||
// gCollisionMesh
|
||||
// Paths
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "TrainCrossing.h"
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include "RaceManager.h"
|
||||
#include "Actor.h"
|
||||
#include "StaticMeshActor.h"
|
||||
#include "particles/ParticleEmitter.h"
|
||||
|
|
@ -50,6 +51,9 @@ public:
|
|||
explicit World();
|
||||
~World();
|
||||
|
||||
RaceManager& GetRaceManager() { return *RaceManagerInstance; }
|
||||
void SetRaceManager(std::unique_ptr<RaceManager> manager) { RaceManagerInstance = std::move(manager); }
|
||||
|
||||
std::shared_ptr<Course> AddCourse(std::shared_ptr<Course> course);
|
||||
|
||||
AActor* AddActor(AActor* actor);
|
||||
|
|
@ -130,7 +134,7 @@ public:
|
|||
std::vector<std::shared_ptr<Course>> Courses;
|
||||
size_t CourseIndex = 0; // For browsing courses.
|
||||
private:
|
||||
|
||||
std::unique_ptr<RaceManager> RaceManagerInstance;
|
||||
};
|
||||
|
||||
extern World gWorldInstance;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,11 @@ AText::AText(const SpawnParams& params) : AActor(params) {
|
|||
* But these need to be checked thoroughly before white-listing.
|
||||
*/
|
||||
std::string AText::ValidateString(const std::string_view& s) {
|
||||
if (s.empty()) { return "Blank Text"; }
|
||||
if (CVarGetInteger("gIsEditorEnabled", false) == true) {
|
||||
if (s.empty()) { return "Blank Text"; }
|
||||
} else {
|
||||
if (s.empty()) { return ""; }
|
||||
}
|
||||
|
||||
Text.clear();
|
||||
|
||||
|
|
@ -100,6 +104,11 @@ std::string AText::ValidateString(const std::string_view& s) {
|
|||
return Text;
|
||||
}
|
||||
|
||||
void AText::SetText(std::string text) {
|
||||
AText::ValidateString(text);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
/*
|
||||
* Most changes during runtime require a refresh because the text is generated statically
|
||||
* with the intention of this code being somewhat performant
|
||||
|
|
@ -353,7 +362,9 @@ void AText::DrawText3D(Camera* camera) { // Based on func_80095BD0
|
|||
|
||||
FrameInterpolation_RecordOpenChild("actor_text", TAG_LETTER(this));
|
||||
gSPDisplayList(gDisplayListHead++, (Gfx*)D_020077A8);
|
||||
switch (1) {
|
||||
|
||||
for (CharacterList& tex : TextureList) {
|
||||
switch (tex.mode) {
|
||||
case 1:
|
||||
gSPDisplayList(gDisplayListHead++, (Gfx*)D_020077F8);
|
||||
break;
|
||||
|
|
@ -361,8 +372,6 @@ void AText::DrawText3D(Camera* camera) { // Based on func_80095BD0
|
|||
gSPDisplayList(gDisplayListHead++, (Gfx*)D_02007818);
|
||||
break;
|
||||
}
|
||||
|
||||
for (CharacterList& tex : TextureList) {
|
||||
//printf("tex texture %p width %d height %d mode %d col %f\n", tex.Texture, tex.width, tex.height, tex.mode, tex.column);
|
||||
gDPLoadTextureTile_4b(gDisplayListHead++, (Gfx*)tex.Texture, G_IM_FMT_I, tex.width, 0, 0, 0, tex.width, tex.height + 2, 0,
|
||||
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
|
||||
|
|
@ -585,4 +594,4 @@ void AText::DrawColourEditor(bool* updated) {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ public:
|
|||
void DrawColourEditor(bool* updated);
|
||||
void FollowPlayer();
|
||||
|
||||
void SetText(std::string text);
|
||||
|
||||
std::string ValidateString(const std::string_view& text);
|
||||
void Refresh();
|
||||
void Print3D(char* text, s32 tracking, s32 mode);
|
||||
|
|
|
|||
|
|
@ -90,7 +90,6 @@ Cup* gBattleCup;
|
|||
ModelLoader gModelLoader;
|
||||
|
||||
HarbourMastersIntro gMenuIntro;
|
||||
Rulesets gRulesets;
|
||||
|
||||
Editor::Editor gEditor;
|
||||
|
||||
|
|
@ -194,14 +193,6 @@ void HM_DrawIntro() {
|
|||
gMenuIntro.HM_DrawIntro();
|
||||
}
|
||||
|
||||
void CM_SpawnFromLevelProps() {
|
||||
// Spawning actors needs to be delayed to the correct time.
|
||||
// And loadlevel needs to happen asap
|
||||
|
||||
//Editor::LoadLevel(nullptr);
|
||||
// Editor::SpawnFromLevelProps();
|
||||
}
|
||||
|
||||
// Set default course; mario raceway
|
||||
void SetMarioRaceway(void) {
|
||||
SetCourseById(0);
|
||||
|
|
@ -239,10 +230,7 @@ const char* GetCupName(void) {
|
|||
}
|
||||
|
||||
void LoadCourse() {
|
||||
if (gWorldInstance.CurrentCourse) {
|
||||
gRulesets.PreLoad();
|
||||
gWorldInstance.CurrentCourse->Load();
|
||||
}
|
||||
gWorldInstance.GetRaceManager().Load();
|
||||
}
|
||||
|
||||
size_t GetCourseIndex() {
|
||||
|
|
@ -383,28 +371,15 @@ void CM_DrawStaticMeshActors() {
|
|||
}
|
||||
|
||||
void CM_BeginPlay() {
|
||||
auto course = gWorldInstance.CurrentCourse;
|
||||
|
||||
if (course) {
|
||||
Editor::LoadLevel(course.get(), course->SceneFilePtr);
|
||||
|
||||
gRulesets.PreInit();
|
||||
// Do not spawn finishline in credits or battle mode. And if bSpawnFinishline.
|
||||
if ((gGamestate != CREDITS_SEQUENCE) && (gModeSelection != BATTLE)) {
|
||||
if (course->bSpawnFinishline) {
|
||||
if (course->FinishlineSpawnPoint.has_value()) {
|
||||
AFinishline::Spawn(course->FinishlineSpawnPoint.value(), IRotator(0, 0, 0));
|
||||
} else {
|
||||
AFinishline::Spawn();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
gEditor.AddLight("Sun", nullptr, D_800DC610[1].l->l.dir);
|
||||
|
||||
course->BeginPlay();
|
||||
gRulesets.PostInit();
|
||||
if (gWorldInstance.CurrentCourse) {
|
||||
// This line should likely be moved.
|
||||
// It's here so PreInit is after the scene file has been loaded
|
||||
// It used to be at the start of BeginPlay
|
||||
Editor::LoadLevel(gWorldInstance.CurrentCourse.get(), gWorldInstance.CurrentCourse->SceneFilePtr);
|
||||
}
|
||||
gWorldInstance.GetRaceManager().PreInit();
|
||||
gWorldInstance.GetRaceManager().BeginPlay();
|
||||
gWorldInstance.GetRaceManager().PostInit();
|
||||
}
|
||||
|
||||
void CM_TickObjects() {
|
||||
|
|
@ -451,16 +426,6 @@ void CM_DrawParticles(s32 cameraId) {
|
|||
}
|
||||
}
|
||||
|
||||
// Helps prevents users from forgetting to add a finishline to their course
|
||||
bool CM_DoesFinishlineExist() {
|
||||
for (AActor* actor : gWorldInstance.Actors) {
|
||||
if (dynamic_cast<AFinishline*>(actor)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CM_InitClouds() {
|
||||
if (gWorldInstance.CurrentCourse) {
|
||||
gWorldInstance.CurrentCourse->InitClouds();
|
||||
|
|
@ -661,36 +626,7 @@ void CM_DeleteActor(size_t index) {
|
|||
* Clean up actors and other game objects.
|
||||
*/
|
||||
void CM_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;
|
||||
}
|
||||
|
||||
for (auto& emitter : world->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;
|
||||
}
|
||||
|
||||
gEditor.ClearObjects();
|
||||
gWorldInstance.Actors.clear();
|
||||
gWorldInstance.StaticMeshActors.clear();
|
||||
gWorldInstance.Objects.clear();
|
||||
gWorldInstance.Emitters.clear();
|
||||
gWorldInstance.Lakitus.clear();
|
||||
gWorldInstance.ClearWorld();
|
||||
}
|
||||
|
||||
struct Actor* CM_AddBaseActor() {
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ void HM_InitIntro(void);
|
|||
void HM_TickIntro(void);
|
||||
void HM_DrawIntro(void);
|
||||
|
||||
void CM_SpawnFromLevelProps();
|
||||
|
||||
void CM_DisplayBattleBombKart(s32 playerId, s32 primAlpha);
|
||||
void CM_DrawBattleBombKarts(s32 cameraId);
|
||||
|
||||
|
|
@ -68,8 +66,6 @@ void CM_ActivateSecondLapLakitu(s32 playerId);
|
|||
void CM_ActivateFinalLapLakitu(s32 playerId);
|
||||
void CM_ActivateReverseLakitu(s32 playerId);
|
||||
|
||||
bool CM_DoesFinishlineExist();
|
||||
|
||||
void CM_InitClouds();
|
||||
|
||||
void CM_DrawActors(Camera* camera);
|
||||
|
|
@ -224,4 +220,4 @@ void CM_RunGarbageCollector(void);
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif // _GAME_H
|
||||
#endif // _GAME_H
|
||||
|
|
|
|||
|
|
@ -1318,7 +1318,6 @@ void init_actors_and_load_textures(void) {
|
|||
destroy_all_actors();
|
||||
CM_CleanWorld();
|
||||
|
||||
CM_SpawnFromLevelProps();
|
||||
CM_BeginPlay();
|
||||
spawn_course_actors();
|
||||
}
|
||||
|
|
@ -2896,4 +2895,4 @@ const char* get_actor_resource_location_name(s32 id) {
|
|||
default:
|
||||
return "mk:actor";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue