Mario Kart 64
Loading...
Searching...
No Matches
Course.h
Go to the documentation of this file.
1#ifndef ENGINE_COURSE_H
2#define ENGINE_COURSE_H
3
4#include <libultraship.h>
5#include "CoreMath.h"
6
7#ifdef __cplusplus
10extern "C" {
11#endif
12
13#include "camera.h"
14#include "course_offsets.h"
15#include "data/some_data.h"
16#include "defines.h"
17#include "bomb_kart.h"
18#include "path_spawn_metadata.h"
19#include "waypoints.h"
20#include "sounds.h"
21#include "common_structs.h"
22
23#ifdef __cplusplus
24}
25#endif
26
37
38// Extends infinitely in the Y direction
39// If a player is overtop of a water volume then it should use its height
40// Recommend using the new water surface type. This is here to support the stock tracks.
41// Albeit, there's no reason you cannot use this so long as you input a square.
42// How to use: WaterVolumes.push_back({0, -100, 100, -100, 100});
44 float Height; // Y coordinate of the Water level
45 float MinX;
46 float MaxX;
47 float MinZ;
48 float MaxZ;
49};
50
51typedef struct MinimapProps {
52 const char* Texture;
53 int16_t Width;
54 int16_t Height;
55 IVector2D Pos[2]; // Minimap position for players 1 and 2. 3/4 player mode is hard-coded to the center.
56 int32_t PlayerX; // The offset to place the player markers
57 int32_t PlayerY;
58 float PlayerScaleFactor; // Scale factor of the player markers
59 float FinishlineX; // The offset to place the finishline texture on the minimap
61 RGB8 Colour; // Colour of the visible pixels (the track path)
63
64void ResizeMinimap(MinimapProps* minimap);
65
66typedef struct Properties {
67 char Name[128];
68 char DebugName[128];
69 char CourseLength[128];
72 const char* AIBehaviour;
75 float NearPersp;
76 float FarPersp;
77 int16_t* AIDistance;
86 uint8_t* CloudTexture;
92 float WaterLevel; // Used for effects, and Lakitu pick up height. Not necessarily the visual water model height.
93
94#ifdef __cplusplus
95 nlohmann::json to_json() const {
96 nlohmann::json j;
97 // j["Id"] = Id ? Id : "";
98 j["Name"] = Name ? Name : "";
99 j["DebugName"] = DebugName ? DebugName : "";
100 j["CourseLength"] = CourseLength ? CourseLength : "";
101 //j["AIBehaviour"] = AIBehaviour ? AIBehaviour : "";
102 j["LakituTowType"] = LakituTowType;
103 j["AIMaximumSeparation"] = AIMaximumSeparation;
104 j["AIMinimumSeparation"] = AIMinimumSeparation;
105 j["NearPersp"] = NearPersp;
106 j["FarPersp"] = FarPersp;
107
108 // AIDistance as a JSON array
109 j["AIDistance"] = std::vector<int16_t>(AIDistance, AIDistance + 32); // gAIDistances array size of 32
110
111 j["AISteeringSensitivity"] = AISteeringSensitivity;
112
113 // PathSizes - Assuming _struct_gCoursePathSizes_0x10 can be serialized similarly
114 // j["PathSizes"] = PathSizes; // Implement your serialization logic here
115
116 j["CurveTargetSpeed"] = { CurveTargetSpeed[0], CurveTargetSpeed[1], CurveTargetSpeed[2], CurveTargetSpeed[3] };
117 j["NormalTargetSpeed"] = { NormalTargetSpeed[0], NormalTargetSpeed[1], NormalTargetSpeed[2], NormalTargetSpeed[3] };
118 j["D_0D0096B8"] = { D_0D0096B8[0], D_0D0096B8[1], D_0D0096B8[2], D_0D0096B8[3] };
119 j["OffTrackTargetSpeed"] = { OffTrackTargetSpeed[0], OffTrackTargetSpeed[1], OffTrackTargetSpeed[2], OffTrackTargetSpeed[3] };
120
121 // Serialize arrays PathTable and PathTable2 (convert pointers into a JSON array if possible)
122 //j["PathTable"] = {{}};
123 //j["PathTable2"] = {{}};
124 // Populate PathTable and PathTable2
125
126 //j["Clouds"] = Clouds ? nlohmann::json{{"x", Clouds->x, "y", Clouds->y, "z", Clouds->z}} : nullptr;
127 //j["CloudList"] = CloudList ? nlohmann::json{{"x", CloudList->x, "y", CloudList->y, "z", CloudList->z}} : nullptr;
128
129 j["MinimapPosition"] = {Minimap.Pos[0].X, Minimap.Pos[0].Y};
130 j["MinimapPosition2P"] = {Minimap.Pos[1].X, Minimap.Pos[1].Y};
131 j["MinimapPlayerX"] = Minimap.PlayerX;
132 j["MinimapPlayerY"] = Minimap.PlayerY;
133 j["MinimapPlayerScaleFactor"] = Minimap.PlayerScaleFactor;
134 j["MinimapFinishlineX"] = Minimap.FinishlineX;
135 j["MinimapFinishlineY"] = Minimap.FinishlineY;
136 j["MinimapColour"] = {static_cast<int>(Minimap.Colour.r), static_cast<int>(Minimap.Colour.g), static_cast<int>(Minimap.Colour.b)};
137 // SkyboxColors - assuming SkyboxColors can be serialized similarly
138
139 #define TO_INT(value) static_cast<int>(value)
140 j["Skybox"] = {
141 TO_INT(Skybox.TopRight.r), TO_INT(Skybox.TopRight.g), TO_INT(Skybox.TopRight.b),
142 TO_INT(Skybox.BottomRight.r), TO_INT(Skybox.BottomRight.g), TO_INT(Skybox.BottomRight.b),
143 TO_INT(Skybox.BottomLeft.r), TO_INT(Skybox.BottomLeft.g), TO_INT(Skybox.BottomLeft.b),
144 TO_INT(Skybox.TopLeft.r), TO_INT(Skybox.TopLeft.g), TO_INT(Skybox.TopLeft.b),
145 TO_INT(Skybox.FloorTopRight.r), TO_INT(Skybox.FloorTopRight.g), TO_INT(Skybox.FloorTopRight.b),
146 TO_INT(Skybox.FloorBottomRight.r), TO_INT(Skybox.FloorBottomRight.g), TO_INT(Skybox.FloorBottomRight.b),
147 TO_INT(Skybox.FloorBottomLeft.r), TO_INT(Skybox.FloorBottomLeft.g), TO_INT(Skybox.FloorBottomLeft.b),
148 TO_INT(Skybox.FloorTopLeft.r), TO_INT(Skybox.FloorTopLeft.g), TO_INT(Skybox.FloorTopLeft.b)
149 };
150 j["Sequence"] = static_cast<int>(Sequence);
151
152 j["WaterLevel"] = static_cast<float>(WaterLevel);
153 #undef CAST_TO_INT
154
155 return j;
156 }
157
158 // Function to load struct from JSON
159 void from_json(const nlohmann::json& j) {
160 //Id = j.at("Id").get<std::string>().c_str();
161// Name = j.at("Name").get<std::string>().c_str();
162 strncpy(Name, j.at("Name").get<std::string>().c_str(), sizeof(Name) - 1);
163 Name[sizeof(Name) - 1] = '\0'; // Ensure null termination
164
165// DebugName = j.at("DebugName").get<std::string>().c_str();
166 strncpy(DebugName, j.at("DebugName").get<std::string>().c_str(), sizeof(DebugName) - 1);
167 DebugName[sizeof(DebugName) - 1] = '\0'; // Ensure null termination
168
169 // CourseLength = j.at("CourseLength").get<std::string>().c_str();
170 strncpy(CourseLength, j.at("CourseLength").get<std::string>().c_str(), sizeof(CourseLength) - 1);
171 CourseLength[sizeof(CourseLength) - 1] = '\0'; // Ensure null termination
172
173 //AIBehaviour = j.at("AIBehaviour").get<std::string>().c_str();
174 LakituTowType = j.at("LakituTowType").get<int>();
175
176 AIMaximumSeparation = j.at("AIMaximumSeparation").get<float>();
177 AIMinimumSeparation = j.at("AIMinimumSeparation").get<float>();
178 NearPersp = j.at("NearPersp").get<float>();
179 FarPersp = j.at("FarPersp").get<float>();
180
181 const auto temp = j.at("AIDistance").get<std::vector<int16_t>>();
182
183 // Ensure the vector has 32 entries
184 if (temp.size() == 32) {
185 // Copy the data into the existing AIDistances array
186 std::copy(temp.begin(), temp.end(), AIDistance);
187 } else {
188 printf("Course::from_json() AIDistance array not size of 32\n");
189 }
190
191 AISteeringSensitivity = j.at("AISteeringSensitivity").get<uint32_t>();
192
193 // Deserialize PathSizes and other custom structs if needed
194
195 CurveTargetSpeed[0] = j.at("CurveTargetSpeed")[0].get<float>();
196 CurveTargetSpeed[1] = j.at("CurveTargetSpeed")[1].get<float>();
197 CurveTargetSpeed[2] = j.at("CurveTargetSpeed")[2].get<float>();
198 CurveTargetSpeed[3] = j.at("CurveTargetSpeed")[3].get<float>();
199
200 NormalTargetSpeed[0] = j.at("NormalTargetSpeed")[0].get<float>();
201 NormalTargetSpeed[1] = j.at("NormalTargetSpeed")[1].get<float>();
202 NormalTargetSpeed[2] = j.at("NormalTargetSpeed")[2].get<float>();
203 NormalTargetSpeed[3] = j.at("NormalTargetSpeed")[3].get<float>();
204
205 D_0D0096B8[0] = j.at("D_0D0096B8")[0].get<float>();
206 D_0D0096B8[1] = j.at("D_0D0096B8")[1].get<float>();
207 D_0D0096B8[2] = j.at("D_0D0096B8")[2].get<float>();
208 D_0D0096B8[3] = j.at("D_0D0096B8")[3].get<float>();
209
210 OffTrackTargetSpeed[0] = j.at("OffTrackTargetSpeed")[0].get<float>();
211 OffTrackTargetSpeed[1] = j.at("OffTrackTargetSpeed")[1].get<float>();
212 OffTrackTargetSpeed[2] = j.at("OffTrackTargetSpeed")[2].get<float>();
213 OffTrackTargetSpeed[3] = j.at("OffTrackTargetSpeed")[3].get<float>();
214
215 // Deserialize arrays PathTable and PathTable2 similarly
216
217 //Clouds = nullptr; // Deserialize if data is present
218 //CloudList = nullptr; // Deserialize if data is present
219 Minimap.Pos[0].X = j.at("MinimapPosition")[0].get<int32_t>();
220 Minimap.Pos[0].Y = j.at("MinimapPosition")[1].get<int32_t>();
221 Minimap.Pos[1].X = j.at("MinimapPosition2P")[0].get<int32_t>();
222 Minimap.Pos[1].Y = j.at("MinimapPosition2P")[1].get<int32_t>();
223 Minimap.PlayerX = j.at("MinimapPlayerX").get<int32_t>();
224 Minimap.PlayerY = j.at("MinimapPlayerY").get<int32_t>();
225 Minimap.PlayerScaleFactor = j.at("MinimapPlayerScaleFactor").get<float>();
226 Minimap.FinishlineX = j.at("MinimapFinishlineX").get<float>();
227 Minimap.FinishlineY = j.at("MinimapFinishlineY").get<float>();
228 Minimap.Colour.r = j.at("MinimapColour")[0].get<uint8_t>();
229 Minimap.Colour.g = j.at("MinimapColour")[1].get<uint8_t>();
230 Minimap.Colour.b = j.at("MinimapColour")[2].get<uint8_t>();
231 //textures = nullptr; // Deserialize textures if present
232
233 Skybox.TopRight.r = j.at("Skybox")[0].get<uint8_t>();
234 Skybox.TopRight.g = j.at("Skybox")[1].get<uint8_t>();
235 Skybox.TopRight.b = j.at("Skybox")[2].get<uint8_t>();
236
237 Skybox.BottomRight.r = j.at("Skybox")[3].get<uint8_t>();
238 Skybox.BottomRight.g = j.at("Skybox")[4].get<uint8_t>();
239 Skybox.BottomRight.b = j.at("Skybox")[5].get<uint8_t>();
240
241 Skybox.BottomLeft.r = j.at("Skybox")[6].get<uint8_t>();
242 Skybox.BottomLeft.g = j.at("Skybox")[7].get<uint8_t>();
243 Skybox.BottomLeft.b = j.at("Skybox")[8].get<uint8_t>();
244
245 Skybox.TopLeft.r = j.at("Skybox")[9].get<uint8_t>();
246 Skybox.TopLeft.g = j.at("Skybox")[10].get<uint8_t>();
247 Skybox.TopLeft.b = j.at("Skybox")[11].get<uint8_t>();
248
249 Skybox.FloorTopRight.r = j.at("Skybox")[12].get<uint8_t>();
250 Skybox.FloorTopRight.g = j.at("Skybox")[13].get<uint8_t>();
251 Skybox.FloorTopRight.b = j.at("Skybox")[14].get<uint8_t>();
252
253 Skybox.FloorBottomRight.r = j.at("Skybox")[15].get<uint8_t>();
254 Skybox.FloorBottomRight.g = j.at("Skybox")[16].get<uint8_t>();
255 Skybox.FloorBottomRight.b = j.at("Skybox")[17].get<uint8_t>();
256
257 Skybox.FloorBottomLeft.r = j.at("Skybox")[18].get<uint8_t>();
258 Skybox.FloorBottomLeft.g = j.at("Skybox")[19].get<uint8_t>();
259 Skybox.FloorBottomLeft.b = j.at("Skybox")[20].get<uint8_t>();
260
261 Skybox.FloorTopLeft.r = j.at("Skybox")[21].get<uint8_t>();
262 Skybox.FloorTopLeft.g = j.at("Skybox")[22].get<uint8_t>();
263 Skybox.FloorTopLeft.b = j.at("Skybox")[23].get<uint8_t>();
264
265 Sequence = static_cast<MusicSeq>(j.at("Sequence").get<int>());
266 WaterLevel = j.at("WaterLevel").get<float>();
267 }
268 void SetText(char* name, const char* title, size_t bufferSize) {
269 // Copy the title into the name buffer, ensuring it's null-terminated and within bounds
270 std::strncpy(name, title, bufferSize - 1);
271 name[bufferSize - 1] = '\0'; // Ensure the string is null-terminated
272 }
273
274 const char* GetName() {
275 return Name;
276 }
277
278 void New() {
279 SetText(Name, "", sizeof(Name));
280 SetText(DebugName, "", sizeof(DebugName));
281 SetText(CourseLength, "", sizeof(CourseLength));
282 }
283#endif
284
286
287#ifdef __cplusplus
288
289class World; // <-- Forward declare
290
291class Course {
292
293public:
294 std::string Id;
295 Properties Props;
296
297 // This allows multiple water levels in a map.
298 // Ex. DK Jungle where there's a waterfall and you can drive above and below it.
299 std::vector<WaterVolume> WaterVolumes;
300
301 const char* vtx = nullptr;
302 const char* gfx = nullptr;
303 size_t gfxSize = 0;
304 const course_texture* textures = nullptr;
305 bool bSpawnFinishline = true;
306 std::optional<FVector> FinishlineSpawnPoint;
307 std::string TrackSectionsPtr;
308 bool bIsMod = false;
309
310 virtual ~Course() = default;
311
312 explicit Course();
313
314 virtual void LoadO2R(std::string trackPath); // Load custom track from o2r
315 virtual void Load(); // Decompress and load stock courses or from o2r but TrackSectionsPtr must be set.
316 virtual void Load(Vtx* vtx, Gfx *gfx); // Load custom track from code. Load must be overridden and then call to this base class method impl.
317 virtual void LoadTextures();
318 virtual void ParseCourseSections(TrackSectionsO2R* sections, size_t size);
319
324 virtual void BeginPlay();
325 virtual void TestPath();
326 virtual void InitClouds();
327 virtual void UpdateClouds(s32, Camera*);
328 virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7);
329 virtual void InitCourseObjects();
330 virtual void UpdateCourseObjects();
331 virtual void RenderCourseObjects(s32 cameraId);
332 virtual void SomeSounds();
333 virtual void CreditsSpawnActors();
334 virtual void WhatDoesThisDo(Player*, int8_t);
335 virtual void WhatDoesThisDoAI(Player*, int8_t);
336 virtual void SetStaffGhost();
337 virtual void Render(struct UnkStruct_800DC5EC*);
338 virtual void RenderCredits();
339 virtual void Waypoints(Player* player, int8_t playerId);
340 virtual f32 GetWaterLevel(FVector pos, Collision* collision);
341 virtual void ScrollingTextures();
342 virtual void DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot,
343 uint16_t playerDirection);
344 virtual void Destroy();
345 virtual bool IsMod();
346
347 private:
348 void Init();
349};
350
351#endif
352
353#endif // ENGINE_COURSE_H
struct Properties Properties
void ResizeMinimap(MinimapProps *minimap)
Definition Course.cpp:30
Definition World.h:42
f32 Vec3f[3]
Definition common_structs.h:10
f32 Vec4f[4]
Definition common_structs.h:11
#define j
void Destroy()
Definition ImguiUI.cpp:97
@ f32
Definition GenericArray.h:59
struct StarData CloudData
MusicSeq
Definition sounds.h:118
Definition CoreMath.h:101
Definition Course.h:51
IVector2D Pos[2]
Definition Course.h:55
int16_t Width
Definition Course.h:53
RGB8 Colour
Definition Course.h:61
float FinishlineY
Definition Course.h:60
int32_t PlayerY
Definition Course.h:57
const char * Texture
Definition Course.h:52
float PlayerScaleFactor
Definition Course.h:58
float FinishlineX
Definition Course.h:59
int32_t PlayerX
Definition Course.h:56
int16_t Height
Definition Course.h:54
Definition Course.h:66
char Name[128]
Definition Course.h:67
uint8_t * CloudTexture
Definition Course.h:86
const course_texture * textures
Definition Course.h:90
_struct_gCoursePathSizes_0x10 PathSizes
Definition Course.h:79
CloudData * Clouds
Definition Course.h:87
Vec4f D_0D0096B8
Definition Course.h:82
Vec4f CurveTargetSpeed
Definition Course.h:80
float AIMaximumSeparation
Definition Course.h:73
TrackPathPoint * PathTable2[4]
Definition Course.h:85
float WaterLevel
Definition Course.h:92
int32_t LakituTowType
Definition Course.h:70
Vec4f OffTrackTargetSpeed
Definition Course.h:83
uint32_t AISteeringSensitivity
Definition Course.h:78
TrackPathPoint * PathTable[4]
Definition Course.h:84
const char * AIBehaviour
Definition Course.h:72
char CourseLength[128]
Definition Course.h:69
float NearPersp
Definition Course.h:75
SkyboxColours Skybox
Definition Course.h:89
float AIMinimumSeparation
Definition Course.h:74
enum MusicSeq Sequence
Definition Course.h:91
int16_t * AIDistance
Definition Course.h:77
char DebugName[128]
Definition Course.h:68
CloudData * CloudList
Definition Course.h:88
float FarPersp
Definition Course.h:76
MinimapProps Minimap
Definition Course.h:71
Vec4f NormalTargetSpeed
Definition Course.h:81
Definition common_structs.h:427
Definition Course.h:27
RGB8 BottomLeft
Definition Course.h:30
RGB8 FloorBottomRight
Definition Course.h:33
RGB8 BottomRight
Definition Course.h:29
RGB8 FloorBottomLeft
Definition Course.h:34
RGB8 TopRight
Definition Course.h:28
RGB8 TopLeft
Definition Course.h:31
RGB8 FloorTopRight
Definition Course.h:32
RGB8 FloorTopLeft
Definition Course.h:35
Definition waypoints.h:14
Definition Course.h:43
float Height
Definition Course.h:44
float MaxX
Definition Course.h:46
float MinZ
Definition Course.h:47
float MinX
Definition Course.h:45
float MaxZ
Definition Course.h:48
Definition path_spawn_metadata.h:9
Definition course_offsets.h:10