summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/code_800029B0.c2
-rw-r--r--src/code_800029B0.h1
-rw-r--r--src/engine/Rulesets.cpp48
-rw-r--r--src/engine/Rulesets.h11
-rw-r--r--src/engine/courses/KalimariDesert.cpp4
-rw-r--r--src/engine/courses/ToadsTurnpike.cpp5
-rw-r--r--src/engine/objects/BombKart.cpp5
-rw-r--r--src/port/Game.cpp5
-rw-r--r--src/port/ui/PortMenu.cpp67
-rw-r--r--src/port/ui/PortMenu.h1
-rw-r--r--src/racing/memory.c8
-rw-r--r--src/racing/memory.h2
12 files changed, 152 insertions, 7 deletions
diff --git a/src/code_800029B0.c b/src/code_800029B0.c
index 32473d14b..562a9fa3a 100644
--- a/src/code_800029B0.c
+++ b/src/code_800029B0.c
@@ -65,7 +65,7 @@ bool gIsEditorPaused = false;
u8* pAppNmiBuffer = (u8*) &osAppNmiBuffer;
s32 gIsMirrorMode = 0;
-f32 vtxStretchY = 1.0f;
+Vec3f gVtxStretch = {1.0f, 1.0f, 1.0f};
Lights1 D_800DC610[] = {
gdSPDefLights1(175, 175, 175, 255, 255, 255, 0, 0, 120),
//! @todo impl lighting in custom track origin value 115 instead of 209. Hack fix for lighting for now
diff --git a/src/code_800029B0.h b/src/code_800029B0.h
index 8556248d8..85fa36b6e 100644
--- a/src/code_800029B0.h
+++ b/src/code_800029B0.h
@@ -66,6 +66,7 @@ extern u8* pAppNmiBuffer;
extern s32 gIsMirrorMode; // D_800DC604
extern s16 gCreditsCourseId;
extern s16 gPlaceItemBoxes;
+extern Vec3f gVtxStretch;
extern CollisionTriangle* gCollisionMesh;
extern u16* gCollisionIndices;
diff --git a/src/engine/Rulesets.cpp b/src/engine/Rulesets.cpp
new file mode 100644
index 000000000..acdbfde2a
--- /dev/null
+++ b/src/engine/Rulesets.cpp
@@ -0,0 +1,48 @@
+#include "Rulesets.h"
+#include "objects/Thwomp.h"
+#include "objects/Trophy.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->State = OThwomp::States::JAILED;
+ }
+ }
+ }
+
+ if (CVarGetInteger("gAllBombKartsChase", false) == true) {
+ for (auto object : gWorldInstance.Objects) {
+ if (OBombKart* kart = dynamic_cast<OBombKart*>(object)) {
+ kart->State = OBombKart::States::CHASE;
+ }
+ }
+ }
+
+ if (CVarGetInteger("gGoFish", false) == true) {
+ gWorldInstance.AddObject(new OTrophy(FVector(0,0,0), OTrophy::TrophyType::GOLD, OTrophy::Behaviour::GO_FISH));
+ }
+}
diff --git a/src/engine/Rulesets.h b/src/engine/Rulesets.h
new file mode 100644
index 000000000..26e67b594
--- /dev/null
+++ b/src/engine/Rulesets.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <libultraship.h>
+#include "World.h"
+
+class Rulesets {
+public:
+ virtual void PreLoad();
+ virtual void PreInit();
+ virtual void PostInit();
+};
diff --git a/src/engine/courses/KalimariDesert.cpp b/src/engine/courses/KalimariDesert.cpp
index 369828581..3ecb3f03d 100644
--- a/src/engine/courses/KalimariDesert.cpp
+++ b/src/engine/courses/KalimariDesert.cpp
@@ -192,6 +192,10 @@ void KalimariDesert::BeginPlay() {
s32 centerWaypoint = 160;
+ _numTrains = CVarGetInteger("gNumTrains", 2);
+ _numCarriages = CVarGetInteger("gNumCarriages", 5);
+ _tender = (ATrain::TenderStatus)CVarGetInteger("gHasTender", 1);
+
// Spawn two trains
for (size_t i = 0; i < _numTrains; ++i) {
uint32_t waypoint = CalculateWaypointDistribution(i, _numTrains, gVehicle2DPathLength, centerWaypoint);
diff --git a/src/engine/courses/ToadsTurnpike.cpp b/src/engine/courses/ToadsTurnpike.cpp
index 0d79cd942..c9f8b9918 100644
--- a/src/engine/courses/ToadsTurnpike.cpp
+++ b/src/engine/courses/ToadsTurnpike.cpp
@@ -176,6 +176,11 @@ void ToadsTurnpike::BeginPlay() {
a /= 2; // Normally vehicle logic is only ran every 2 frames. This slows the vehicles down to match.
b /= 2;
+ _numTrucks = CVarGetInteger("gNumTrucks", 7);
+ _numBuses = CVarGetInteger("gNumBuses", 7);
+ _numTankerTrucks = CVarGetInteger("gNumTankerTrucks", 7);
+ _numCars = CVarGetInteger("gNumCars", 7);
+
// Other game modes spawn seven of each vehicle
if (gModeSelection == TIME_TRIALS) {
_numTrucks = 8;
diff --git a/src/engine/objects/BombKart.cpp b/src/engine/objects/BombKart.cpp
index a9dd3a22e..78d4762a9 100644
--- a/src/engine/objects/BombKart.cpp
+++ b/src/engine/objects/BombKart.cpp
@@ -253,6 +253,11 @@ void OBombKart::Tick() {
}
break;
case States::CHASE:
+ // Prevents chasing during race staging
+ if (gRaceState != RACE_IN_PROGRESS) {
+ return;
+ }
+
if (!_target) {
_target = OBombKart::FindTarget();
} else {
diff --git a/src/port/Game.cpp b/src/port/Game.cpp
index 068651bff..62dec7a16 100644
--- a/src/port/Game.cpp
+++ b/src/port/Game.cpp
@@ -48,6 +48,7 @@
#include "engine/editor/Editor.h"
#include "engine/editor/EditorMath.h"
#include "engine/editor/SceneManager.h"
+#include "engine/Rulesets.h"
#ifdef _WIN32
#include <locale.h>
@@ -84,6 +85,7 @@ Cup* gBattleCup;
ModelLoader gModelLoader;
HarbourMastersIntro gMenuIntro;
+Rulesets gRulesets;
Editor::Editor gEditor;
@@ -236,6 +238,7 @@ const char* GetCupName(void) {
void LoadCourse() {
if (gWorldInstance.CurrentCourse) {
+ gRulesets.PreLoad();
gWorldInstance.CurrentCourse->Load();
}
}
@@ -379,6 +382,7 @@ void CM_BeginPlay() {
auto course = gWorldInstance.CurrentCourse;
if (course) {
+ gRulesets.PreInit();
// Do not spawn finishline in credits or battle mode. And if bSpawnFinishline.
if ((gGamestate != CREDITS_SEQUENCE) && (gModeSelection != BATTLE)) {
if (course->bSpawnFinishline) {
@@ -388,6 +392,7 @@ void CM_BeginPlay() {
gEditor.AddLight("Sun", nullptr, D_800DC610[1].l->l.dir);
course->BeginPlay();
+ gRulesets.PostInit();
}
}
diff --git a/src/port/ui/PortMenu.cpp b/src/port/ui/PortMenu.cpp
index ba180d5b9..13ec40f51 100644
--- a/src/port/ui/PortMenu.cpp
+++ b/src/port/ui/PortMenu.cpp
@@ -10,6 +10,10 @@
#include <tuple>
#include "ResolutionEditor.h"
+#include "courses/Course.h"
+#include "courses/KalimariDesert.h"
+#include "courses/ToadsTurnpike.h"
+
#ifdef __SWITCH__
#include <port/switch/SwitchImpl.h>
#endif
@@ -383,6 +387,8 @@ void PortMenu::AddEnhancements() {
.CVar("gShowSpaghettiVersion")
.Options(CheckboxOptions().Tooltip("Show the Spaghetti Kart version on the Mario Kart menu").DefaultValue(true));
+ AddRulesets();
+
path = { "Enhancements", "Cheats", SECTION_COLUMN_1 };
AddSidebarEntry("Enhancements", "Cheats", 3);
AddWidget(path, "Moon Jump", WIDGET_CVAR_CHECKBOX).CVar("gEnableMoonJump");
@@ -424,6 +430,67 @@ static const std::unordered_map<int32_t, const char*> switchCPUProfiles = {
};
#endif
+void PortMenu::AddRulesets() {
+ WidgetPath path = { "Enhancements", "Rulesets", SECTION_COLUMN_1 };
+ AddSidebarEntry("Enhancements", "Rulesets", 3);
+
+ // Requires more testing
+ // AddWidget(path, "Number of Laps", WIDGET_CVAR_SLIDER_INT)
+ // .CVar("gNumLaps")
+ // .Options(UIWidgets::IntSliderOptions().Min().Max(20).Step(1).DefaultValue(3));
+
+ AddWidget(path, "No Itemboxes", WIDGET_CVAR_CHECKBOX)
+ .CVar("gDisableItemboxes")
+ .Options(CheckboxOptions().Tooltip(
+ "Prevents Itemboxes from spawning"));
+ AddWidget(path, "All Thwomps are Marty", WIDGET_CVAR_CHECKBOX)
+ .CVar("gAllThwompsAreMarty")
+ .Options(CheckboxOptions().Tooltip(
+ "All Thwomps are Marty"));
+ AddWidget(path, "All Bomb Karts in Chase Mode", WIDGET_CVAR_CHECKBOX)
+ .CVar("gAllBombKartsChase")
+ .Options(CheckboxOptions().Tooltip(
+ "These karts will chase you!!!"));
+ AddWidget(path, "Get the trophies!", WIDGET_CVAR_CHECKBOX)
+ .CVar("gGoFish")
+ .Options(CheckboxOptions().Tooltip(
+ "Collect as many trophies as you can. Racer with the most trophies wins!"));
+ AddWidget(path, "Track X Stretch", WIDGET_SLIDER_FLOAT)
+ .ValuePointer(&gVtxStretch[0])
+ .Options(UIWidgets::FloatSliderOptions().Min(0.1f).Max(10.0f).Step(0.1f).Format("%.2f"));
+ AddWidget(path, "Track Y Stretch", WIDGET_SLIDER_FLOAT)
+ .ValuePointer(&gVtxStretch[1])
+ .Options(UIWidgets::FloatSliderOptions().Min(0.1f).Max(10.0f).Step(0.1f).Format("%.2f"));
+ AddWidget(path, "Track Z Stretch", WIDGET_SLIDER_FLOAT)
+ .ValuePointer(&gVtxStretch[2])
+ .Options(UIWidgets::FloatSliderOptions().Min(0.1f).Max(10.0f).Step(0.1f).Format("%.2f"));
+
+
+ AddWidget(path, "Trains", WIDGET_CVAR_SLIDER_INT)
+ .CVar("gNumTrains")
+ .Options(UIWidgets::IntSliderOptions().Min(0).Max(19).Step(1).DefaultValue(2));
+ AddWidget(path, "Carriages", WIDGET_CVAR_SLIDER_INT)
+ .CVar("gNumCarriages")
+ .Options(UIWidgets::IntSliderOptions().Min(0).Max(74).Step(1).DefaultValue(5));
+ AddWidget(path, "Train has a tender", WIDGET_CVAR_CHECKBOX)
+ .CVar("gHasTender")
+ .Options(UIWidgets::CheckboxOptions().DefaultValue(1)
+ .Tooltip("This option is only valid if there are no carriages on the train"));
+
+ AddWidget(path, "Trucks", WIDGET_CVAR_SLIDER_INT)
+ .CVar("gNumTrucks")
+ .Options(UIWidgets::IntSliderOptions().Min(0).Max(50).Step(1).DefaultValue(7));
+ AddWidget(path, "Buses", WIDGET_CVAR_SLIDER_INT)
+ .CVar("gNumBuses")
+ .Options(UIWidgets::IntSliderOptions().Min(0).Max(50).Step(1).DefaultValue(7));
+ AddWidget(path, "Tanker Trucks", WIDGET_CVAR_SLIDER_INT)
+ .CVar("gNumTankerTrucks")
+ .Options(UIWidgets::IntSliderOptions().Min(0).Max(50).Step(1).DefaultValue(7));
+ AddWidget(path, "Cars", WIDGET_CVAR_SLIDER_INT)
+ .CVar("gNumCars")
+ .Options(UIWidgets::IntSliderOptions().Min(0).Max(50).Step(1).DefaultValue(7));
+}
+
void PortMenu::AddDevTools() {
AddMenuEntry("Developer", "gSettings.Menu.DevToolsSidebarSection");
AddSidebarEntry("Developer", "General", 3);
diff --git a/src/port/ui/PortMenu.h b/src/port/ui/PortMenu.h
index a96e3570e..32cb9148e 100644
--- a/src/port/ui/PortMenu.h
+++ b/src/port/ui/PortMenu.h
@@ -65,6 +65,7 @@ class PortMenu : public Ship::Menu {
WidgetInfo& AddWidget(WidgetPath& pathInfo, std::string widgetName, WidgetType widgetType);
void AddSettings();
void AddEnhancements();
+ void AddRulesets();
void AddDevTools();
};
} // namespace BenGui
diff --git a/src/racing/memory.c b/src/racing/memory.c
index 679bbf69e..088f7e3f7 100644
--- a/src/racing/memory.c
+++ b/src/racing/memory.c
@@ -612,19 +612,19 @@ void func_802A86A8(CourseVtx* data, Vtx* vtx, size_t arg1) {
// s32 to uintptr_t comparison required for matching.
for (i = 0; i < arg1; i++) {
if (gIsMirrorMode) {
- vtx->v.ob[0] = -courseVtx->ob[0];
+ vtx->v.ob[0] = -(courseVtx->ob[0] * gVtxStretch[0]);
} else {
- vtx->v.ob[0] = courseVtx->ob[0];
+ vtx->v.ob[0] = courseVtx->ob[0] * gVtxStretch[0];
}
- vtx->v.ob[1] = (courseVtx->ob[1] * vtxStretchY);
+ vtx->v.ob[1] = (courseVtx->ob[1] * gVtxStretch[1]);
temp_a0 = courseVtx->ca[0];
temp_a3 = courseVtx->ca[1];
flags = temp_a0 & 3;
flags |= (temp_a3 << 2) & 0xC;
- vtx->v.ob[2] = courseVtx->ob[2];
+ vtx->v.ob[2] = courseVtx->ob[2] * gVtxStretch[2];
vtx->v.tc[0] = courseVtx->tc[0];
vtx->v.tc[1] = courseVtx->tc[1];
vtx->v.cn[0] = (temp_a0 & 0xFC);
diff --git a/src/racing/memory.h b/src/racing/memory.h
index 557d9f02f..72ecd0eb5 100644
--- a/src/racing/memory.h
+++ b/src/racing/memory.h
@@ -41,8 +41,6 @@ struct AllocOnlyPool {
#define ALIGN4(val) (((val) + 0x3) & ~0x3)
-extern f32 vtxStretchY;
-
u8* load_lakitu_tlut_x64(const char** textureList, size_t length);
void* get_next_available_memory_addr(uintptr_t);
uintptr_t set_segment_base_addr(s32, void*);