Add Rulesets (#494)

This commit is contained in:
MegaMech
2025-07-20 17:13:35 -06:00
committed by GitHub
parent d62d4bb900
commit adc7dd050f
12 changed files with 152 additions and 7 deletions
+1 -1
View File
@@ -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
+1
View File
@@ -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;
+48
View File
@@ -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));
}
}
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include <libultraship.h>
#include "World.h"
class Rulesets {
public:
virtual void PreLoad();
virtual void PreInit();
virtual void PostInit();
};
+4
View File
@@ -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);
+5
View File
@@ -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;
+5
View File
@@ -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 {
+5
View File
@@ -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();
}
}
+67
View File
@@ -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);
+1
View File
@@ -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
+4 -4
View File
@@ -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);
-2
View File
@@ -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*);