diff --git a/courses/koopa_troopa_beach/course_offsets.c b/courses/koopa_troopa_beach/course_offsets.c index 45c5d010d..13a187933 100644 --- a/courses/koopa_troopa_beach/course_offsets.c +++ b/courses/koopa_troopa_beach/course_offsets.c @@ -1,6 +1,7 @@ #include #include "course_offsets.h" #include +#include "animation.h" const course_texture koopa_troopa_beach_textures[] = { { gTexture643B3C, 0x0798, 0x0800, 0x0 }, @@ -241,73 +242,63 @@ Animation d_course_koopa_troopa_beach_unk_data4 = { //! 0x60169b uintptr_t d_course_koopa_troopa_beach_unk4[] = { - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_ADD_POS(0x00000000, 0x00000000, 0x00000000), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_koopa_troopa_beach_dl_16630, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_koopa_troopa_beach_dl_16630), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, 0x00000000, - 0x00000000, 0xfffffffb, 0x00000005, + ANIMATION_ADD_POS(0x00000000, -0x00000005, 0x00000005), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_koopa_troopa_beach_dl_16850, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_koopa_troopa_beach_dl_16850), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_koopa_troopa_beach_dl_168F0, - 0x00000024, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL_AT(d_course_koopa_troopa_beach_dl_168F0, 0x00000024, 0x00000000, 0x00000000), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_koopa_troopa_beach_dl_16990, - 0x00000019, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL_AT(d_course_koopa_troopa_beach_dl_16990, 0x00000019, 0x00000000, 0x00000000), - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000000, 0x00000007, 0x00000000, 0x00000000, - 0x00000000, 0xfffffffb, 0xfffffffb, + ANIMATION_ADD_POS(0x00000000, -0x00000005, -0x00000005), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_koopa_troopa_beach_dl_16850, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_koopa_troopa_beach_dl_16850), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_koopa_troopa_beach_dl_168F0, - 0x00000024, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL_AT(d_course_koopa_troopa_beach_dl_168F0, 0x00000024, 0x00000000, 0x00000000), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_koopa_troopa_beach_dl_16990, - 0x00000019, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL_AT(d_course_koopa_troopa_beach_dl_16990, 0x00000019, 0x00000000, 0x00000000), - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000003, 0x00000002, + ANIMATION_STOP, }; // 0x06016B60 diff --git a/courses/rainbow_road/course_offsets.c b/courses/rainbow_road/course_offsets.c index d17ac3b7c..f7a6d8da5 100644 --- a/courses/rainbow_road/course_offsets.c +++ b/courses/rainbow_road/course_offsets.c @@ -100,40 +100,33 @@ Animation* d_rainbow_road_unk3[] = { // 0x06016110 uintptr_t d_rainbow_road_unk4[] = { - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, 0x00000000, - 0x00000000, 0x0000023a, 0x00000000, + ANIMATION_ADD_POS(0x00000000, 0x0000023a, 0x00000000), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_rainbow_road_dl_15550, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_rainbow_road_dl_15550), - 0x00000000, 0x00000007, 0x00000000, d_course_rainbow_road_dl_151A8, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_rainbow_road_dl_151A8), - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000000, 0x00000007, 0x00000000, 0x00000000, - 0x00000000, 0x0000023a, 0x00000000, + ANIMATION_ADD_POS(0x00000000, 0x0000023a, 0x00000000), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_rainbow_road_dl_15C68, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_rainbow_road_dl_15C68), - 0x00000000, 0x00000007, 0x00000000, d_course_rainbow_road_dl_158C0, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_rainbow_road_dl_158C0), - 0x00000000, 0x00000007, 0x00000000, d_course_rainbow_road_dl_15F18, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_rainbow_road_dl_15F18), - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000003, 0x00000002, + ANIMATION_STOP, }; // No idea what this stuff is diff --git a/courses/sherbet_land/course_offsets.c b/courses/sherbet_land/course_offsets.c index 0ed86ad8d..b597ee828 100644 --- a/courses/sherbet_land/course_offsets.c +++ b/courses/sherbet_land/course_offsets.c @@ -1,6 +1,7 @@ #include #include "course_offsets.h" #include +#include "animation.h" const course_texture sherbet_land_textures[] = { { gTexture643B3C, 0x0798, 0x0800, 0x0 }, { gTexture66D024, 0x04EA, 0x0800, 0x0 }, @@ -66,68 +67,57 @@ const Gfx* sherbet_land_dls_2[] = { }; uintptr_t d_course_sherbet_land_unk_data1[] = { - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_sherbet_land_dl_8D00, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_sherbet_land_dl_8D00), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, 0x00000000, - 0xFFFFFFCD, 0x00000054, 0xFFFFFFF3, + ANIMATION_ADD_POS(-0x00000033, 0x00000054, -0x0000000d), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_sherbet_land_dl_8730, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_sherbet_land_dl_8730), - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000000, 0x00000007, 0x00000000, 0x00000000, - 0x00000033, 0x00000054, 0xFFFFFFF3, + ANIMATION_ADD_POS(0x00000033, 0x00000054, -0x0000000d), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_sherbet_land_dl_8808, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_sherbet_land_dl_8808), - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000000, 0x00000007, 0x00000000, 0x00000000, - 0xFFFFFFDA, 0xFFFFFFCA, 0xFFFFFFF3, + ANIMATION_ADD_POS(-0x00000026, -0x00000036, -0x0000000d), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_sherbet_land_dl_8930, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_sherbet_land_dl_8930), - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000000, 0x00000007, 0x00000000, 0x00000000, - 0x00000026, 0xFFFFFFCA, 0xFFFFFFF3, + ANIMATION_ADD_POS(0x00000026, -0x00000036, -0x0000000d), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_sherbet_land_dl_8A78, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_sherbet_land_dl_8A78), - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000000, 0x00000007, 0x00000000, 0x00000000, - 0x00000000, 0x0000006F, 0xFFFFFFED, + ANIMATION_ADD_POS(0x00000000, 0x0000006F, -0x00000013), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_sherbet_land_dl_8E00, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_sherbet_land_dl_8E00), - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000003, 0x00000002, + ANIMATION_STOP, }; // 0x0600905C diff --git a/courses/test_course/data.c b/courses/test_course/data.c index a39c05dc5..7bbbdb31a 100644 --- a/courses/test_course/data.c +++ b/courses/test_course/data.c @@ -63,7 +63,6 @@ TrackWaypoint test_course_path[] = { { 300, 0, 949, 4}, { 200, 0, 950, 4}, { 100, 0, 950, 4}, - { 0, 0, 950, 1}, // Main point 4 // End of path { -32768, -32768, -32768, 0 } // Terminator diff --git a/courses/yoshi_valley/course_offsets.c b/courses/yoshi_valley/course_offsets.c index 959c2dcc4..7518ece5d 100644 --- a/courses/yoshi_valley/course_offsets.c +++ b/courses/yoshi_valley/course_offsets.c @@ -159,63 +159,55 @@ Animation* d_course_yoshi_valley_unk4[] = { //! 0x06014798 uintptr_t d_course_yoshi_valley_unk5[] = { - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_ADD_POS(0x00000000, 0x00000000, 0x00000000), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_yoshi_valley_dl_142C0, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_yoshi_valley_dl_142C0), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, 0x00000000, - 0x000007f8, 0x00000000, 0x00000000, + ANIMATION_ADD_POS(0x000007f8, 0x00000000, 0x00000000), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_yoshi_valley_dl_143C8, - 0x00000000, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL(d_course_yoshi_valley_dl_143C8), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_yoshi_valley_dl_144A8, - 0x000001cc, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL_AT(d_course_yoshi_valley_dl_144A8, 0x000001cc, 0x00000000, 0x00000000), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_yoshi_valley_dl_14500, - 0x000001cc, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL_AT(d_course_yoshi_valley_dl_14500, 0x000001cc, 0x00000000, 0x00000000), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_yoshi_valley_dl_14558, - 0x00000158, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL_AT(d_course_yoshi_valley_dl_14558, 0x00000158, 0x00000000, 0x00000000), - 0x00000001, 0x00000002, + ANIMATION_DISABLE_AUTOMATIC_POP, - 0x00000000, 0x00000007, 0x00000000, d_course_yoshi_valley_dl_145D0, - 0x00000120, 0x00000000, 0x00000000, + ANIMATION_RENDER_MODEL_AT(d_course_yoshi_valley_dl_145D0, 0x00000120, 0x00000000, 0x00000000), - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000002, 0x00000002, + ANIMATION_POP_MATRIX, - 0x00000003, 0x00000002, + ANIMATION_STOP, }; // No idea what this stuff is diff --git a/include/actor_types.h b/include/actor_types.h index 9c41a2e0d..387aa285e 100644 --- a/include/actor_types.h +++ b/include/actor_types.h @@ -4,6 +4,7 @@ #include #include #include +#include // #pragma GCC diagnostic push // #pragma GCC diagnostic ignored "-Wmicrosoft-extension" @@ -159,9 +160,8 @@ struct RailroadCrossing { /* 0x00 */ s16 type; /* 0x02 */ s16 flags; /* 0x04 */ s16 someTimer; - /* 0x06 */ s16 crossingId; - /* 0x08 */ f32 unk_08; - /* 0x0C */ f32 unk_0C; + /* 0x06 */ s16 crossingId; // unused now + /* 0x08 */ void* crossingTrigger; // Crossing Trigger Class /* 0x10 */ Vec3s rot; /* 0x16 */ s16 unk_16; /* 0x18 */ Vec3f pos; @@ -169,6 +169,9 @@ struct RailroadCrossing { /* 0x30 */ Collision unk30; }; // size = 0x70 +// crossingTrigger might ruin struct size when compiled on 32 bit +static_assert(sizeof(struct RailroadCrossing) == sizeof(struct Actor), "RailroadCrossing struct size does not match base struct size"); + struct FallingRock { /* 0x00 */ s16 type; /* 0x02 */ s16 flags; diff --git a/src/actors/falling_rock/update.inc.c b/src/actors/falling_rock/update.inc.c index b6a4f541b..97d9a2a6b 100644 --- a/src/actors/falling_rock/update.inc.c +++ b/src/actors/falling_rock/update.inc.c @@ -5,7 +5,7 @@ void func_8029CF0C(struct ActorSpawnData* spawnData, struct FallingRock* rock) { #ifndef TARGET_N64 - struct ActorSpawnData* temp_v0 = (struct ActorSpawnData*) LOAD_ASSET(spawnData); + struct ActorSpawnData* temp_v0 = spawnData; #else s32 segment = SEGMENT_NUMBER2(spawnData); s32 offset = SEGMENT_OFFSET(spawnData); @@ -24,21 +24,16 @@ void func_8029CF0C(struct ActorSpawnData* spawnData, struct FallingRock* rock) { } /** - * @brief Spawns falling rocks. + * @brief Spawns falling sRockSpawnData. * Used in Choco Mountain. * * @param spawnData */ -struct ActorSpawnData* rocks; -void spawn_falling_rocks(const char* spawnData) { +static struct ActorSpawnData* sRockSpawnData; +void spawn_falling_rocks(struct ActorSpawnData* spawnData) { #ifndef TARGET_N64 - struct ActorSpawnData* temp_s0; - if (GetCourse() == GetTestCourse()) { - temp_s0 = (struct ActorSpawnData*) spawnData; - } else { - temp_s0 = (struct ActorSpawnData*) LOAD_ASSET(spawnData); - } - rocks = temp_s0; + struct ActorSpawnData* temp_s0 = spawnData; + sRockSpawnData = spawnData; #else s32 addr = SEGMENT_NUMBER2(spawnData); s32 offset = SEGMENT_OFFSET(spawnData); @@ -82,7 +77,7 @@ void update_actor_falling_rocks(struct FallingRock* rock) { return; } if (rock->pos[1] < D_8015F8E4) { - func_8029CF0C(rocks, rock); + func_8029CF0C(sRockSpawnData, rock); } rock->rot[0] += (s16) ((rock->velocity[2] * 5461.0f) / 20.0f); rock->rot[2] += (s16) ((rock->velocity[0] * 5461.0f) / 20.0f); diff --git a/src/actors/railroad_crossing/render.inc.c b/src/actors/railroad_crossing/render.inc.c index e91f56438..adbe7a7e5 100644 --- a/src/actors/railroad_crossing/render.inc.c +++ b/src/actors/railroad_crossing/render.inc.c @@ -27,7 +27,7 @@ void render_actor_railroad_crossing(Camera* arg0, struct RailroadCrossing* rr_cr gSPSetGeometryMode(gDisplayListHead++, G_LIGHTING); gSPClearGeometryMode(gDisplayListHead++, G_CULL_BACK); - if (isCrossingTriggeredByIndex[rr_crossing->crossingId]) { + if (CourseManager_GetCrossingOnTriggered(rr_crossing->crossingTrigger)) { if (rr_crossing->someTimer < 20) { gSPDisplayList(gDisplayListHead++, d_course_kalimari_desert_dl_crossing_right_active); diff --git a/src/actors/railroad_crossing/update.inc.c b/src/actors/railroad_crossing/update.inc.c index f65376674..5e1c54ca1 100644 --- a/src/actors/railroad_crossing/update.inc.c +++ b/src/actors/railroad_crossing/update.inc.c @@ -9,7 +9,7 @@ */ void update_actor_railroad_crossing(struct RailroadCrossing* crossing) { // If train close? - if (isCrossingTriggeredByIndex[crossing->crossingId] != 0) { + if (CourseManager_GetCrossingOnTriggered(crossing->crossingTrigger)) { // Timer++ crossing->someTimer++; // Reset timer diff --git a/src/animation.c b/src/animation.c index 7fed594d5..19204641e 100644 --- a/src/animation.c +++ b/src/animation.c @@ -95,10 +95,10 @@ void render_limb_or_add_mtx(Armature* arg0, s16* arg1, AnimationLimbVector arg2, mtxf_translate_rotate2(modelMatrix, pos, angle); convert_to_fixed_point_matrix_animation(&gGfxPool->mtxHud[gMatrixHudCount], modelMatrix); sMatrixStackSize += 1; - gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL2(&gGfxPool->mtxHud[gMatrixHudCount++]), + gSPMatrix(gDisplayListHead++, (&gGfxPool->mtxHud[gMatrixHudCount++]), G_MTX_PUSH | G_MTX_MUL | G_MTX_MODELVIEW); if (virtualModel != NULL) { - model = segmented_to_virtual(virtualModel); + model = (virtualModel); gSPDisplayList(gDisplayListHead++, model); } } @@ -111,8 +111,10 @@ void render_armature(Armature* animation, Animation* arg1, s16 timeCycle) { s32 animation_type; s32 someIndex; - angle_array = segmented_to_virtual(arg1->angle_array); - animation_cycle_list = segmented_to_virtual(arg1->animation_cycle_spec_vector); + printf("model: %d %d %d\n", animation->pos[0], animation->pos[1], animation->pos[2]); + + angle_array = (arg1->angle_array); + animation_cycle_list = (arg1->animation_cycle_spec_vector); sMatrixStackSize = 0; isNotTheFirst = 0; for (someIndex = 0; someIndex < 3; someIndex++) { @@ -157,9 +159,9 @@ s16 render_animated_model(Armature* virtualArmature, Animation** virtualListAnim Animation* animation; Animation** listAnimation; - armature = segmented_to_virtual(virtualArmature); - listAnimation = segmented_to_virtual(virtualListAnimation); // Convert the array's address - animation = segmented_to_virtual(listAnimation[animationIndex]); // Convert an array element's address + armature = (virtualArmature); + listAnimation = (virtualListAnimation); // Convert the array's address + animation = (listAnimation[animationIndex]); // Convert an array element's address if (timeCycle >= animation->animation_length) { timeCycle = 0; } @@ -172,8 +174,7 @@ s16 render_animated_model(Armature* virtualArmature, Animation** virtualListAnim } s16 get_animation_length(Animation** addr, s16 offset) { - Animation** item = segmented_to_virtual(addr); - Animation* temp = (Animation*) segmented_to_virtual((void*) item[offset]); - + Animation** item = (addr); + Animation* temp = (Animation*) ((void*) item[offset]); return temp->animation_length - 1; } diff --git a/src/code_80005FD0.c b/src/code_80005FD0.c index 8fe8145a4..1cc9c990a 100644 --- a/src/code_80005FD0.c +++ b/src/code_80005FD0.c @@ -146,7 +146,6 @@ s32 D_801634F4; Test D_801634F8[10]; Path2D* gVehicle2DWaypoint; s32 gVehicle2DWaypointLength; -size_t gNumTrains = 0; TrainStuff gTrainList[NUM_TRAINS]; u16 isCrossingTriggeredByIndex[NUM_CROSSINGS]; u16 sCrossingActiveTimer[NUM_CROSSINGS]; @@ -1554,7 +1553,7 @@ void update_vehicles(void) { } } - CourseManager_UpdateVehicles(); + CourseManager_VehiclesTick(); } } @@ -1679,13 +1678,16 @@ void func_80009B60(s32 playerId) { if (!(player->unk_0CA & 2) && !(player->unk_0CA & 8)) { D_80163448 = gPathIndexByPlayerId[playerId]; func_80008DC0(D_80163448); - if (GetCourse() == GetKalimariDesert()) { - func_80012DC0(playerId, player); + //if (GetCourse() == GetKalimariDesert()) { + CourseManager_VehiclesCollision(playerId, player); + //func_80012DC0(playerId, player); if (playerId == 0) { - func_80013054(); + CourseManager_CrossingTrigger(); + //func_80013054(); } - } else if (GetCourse() == GetDkJungle()) { - func_80013854(player); + //} + if (GetCourse() == GetDkJungle()) { + //func_80013854(player); } else if (GetCourse() == GetToadsTurnpike()) { func_800148C4(playerId, player); func_80014A18(playerId, player); @@ -1741,13 +1743,15 @@ void func_80009B60(s32 playerId) { } D_801631F8[playerId] = D_801631E0[playerId]; + CourseManager_RenderTrucks(playerId); + if ((GetCourse() == GetYoshiValley()) || (GetCourse() == GetPodiumCeremony())) { D_801634F8[playerId].unk4 = 0.0f; } else if (GetCourse() == GetToadsTurnpike()) { - func_8001490C(playerId); - func_80014A60(playerId); - func_80014BB4(playerId); - func_80014D08(playerId); + // func_8001490C(playerId); + // func_80014A60(playerId); + // func_80014BB4(playerId); + // func_80014D08(playerId); } if (D_801631E0[playerId] == 1) { @@ -1769,7 +1773,8 @@ void func_80009B60(s32 playerId) { } else { D_80163210[playerId] = CourseManager_GetProps()->D_0D009568[gCCSelection]; } - check_ai_crossing_distance(playerId); + CourseManager_AICrossingBehaviour(playerId); + //check_ai_crossing_distance(playerId); func_8000D3B8(playerId); func_8000D438(playerId, D_801630E0); temp_f0 = D_80162FA0[0] - player->pos[0]; @@ -1983,7 +1988,8 @@ void func_80009B60(s32 playerId) { D_8016320C = D_80163028[playerId]; player->effects &= ~0x00200000; D_80163210[playerId] = D_8016320C; - check_ai_crossing_distance(playerId); + CourseManager_AICrossingBehaviour(playerId); + //check_ai_crossing_distance(playerId); func_80008424(playerId, D_8016320C, player); } } @@ -2917,25 +2923,22 @@ void set_bomb_kart_spawn_positions(void) { for (var_s3 = 0; var_s3 < NUM_BOMB_KARTS_VERSUS; var_s3++) { bombKartSpawn = &gBombKartSpawns[gCurrentCourseId][var_s3]; - switch (gCurrentCourseId) { - case COURSE_YOSHI_VALLEY: - startingXPos = bombKartSpawn->startingXPos; - startingZPos = bombKartSpawn->startingZPos; - startingYPos = spawn_actor_on_surface(startingXPos, 2000.0f, startingZPos); - break; - case COURSE_AWARD_CEREMONY: - temp_v0 = &D_80164550[3][bombKartSpawn->waypointIndex]; - startingXPos = temp_v0->posX; - startingYPos = temp_v0->posY; - startingZPos = temp_v0->posZ; - break; - default: - temp_v0 = &D_80164550[0][bombKartSpawn->waypointIndex]; - startingXPos = temp_v0->posX; - startingYPos = temp_v0->posY; - startingZPos = temp_v0->posZ; - break; + if (GetCourse() == GetYoshiValley()) { + startingXPos = bombKartSpawn->startingXPos; + startingZPos = bombKartSpawn->startingZPos; + startingYPos = spawn_actor_on_surface(startingXPos, 2000.0f, startingZPos); + } else if (GetCourse() == GetPodiumCeremony()) { + temp_v0 = &D_80164550[3][bombKartSpawn->waypointIndex]; + startingXPos = temp_v0->posX; + startingYPos = temp_v0->posY; + startingZPos = temp_v0->posZ; + } else { + temp_v0 = &D_80164550[0][bombKartSpawn->waypointIndex]; + startingXPos = temp_v0->posX; + startingYPos = temp_v0->posY; + startingZPos = temp_v0->posZ; } + gBombKarts[var_s3].bombPos[0] = startingXPos; gBombKarts[var_s3].bombPos[1] = startingYPos; gBombKarts[var_s3].bombPos[2] = startingZPos; @@ -3457,36 +3460,9 @@ void func_8000F2DC(void) { D_80164430 = *gWaypointCountByPathIndex; - switch (gCurrentCourseId) { - case COURSE_KALAMARI_DESERT: - generate_train_waypoints(d_course_kalimari_desert_track_unknown_waypoints); - init_vehicles_trains(0, 5, 5.0f); - init_vehicles_trains(1, 5, 5.0f); - break; - case COURSE_DK_JUNGLE: - generate_ferry_waypoints(); - init_vehicles_ferry(); - break; - case COURSE_TOADS_TURNPIKE: - init_vehicles_box_trucks(); - init_vehicles_school_buses(); - init_vehicles_trucks(); - init_vehicles_cars(); - break; - } - if (GetCourse() == GetKalimariDesert()) { - generate_train_waypoints(d_course_kalimari_desert_track_unknown_waypoints); - init_vehicles_trains(0, 5, 5.0f); - init_vehicles_trains(1, 5, 5.0f); - } else if (GetCourse() == GetDkJungle()) { - generate_ferry_waypoints(); - init_vehicles_ferry(); - } else if (GetCourse() == GetToadsTurnpike()) { - init_vehicles_box_trucks(); - init_vehicles_school_buses(); - init_vehicles_trucks(); - init_vehicles_cars(); - } + CourseManager_ResetVehicles(); + + CourseManager_SpawnVehicles(); CourseManager_SpawnBombKarts(); set_bomb_kart_spawn_positions(); @@ -3658,8 +3634,6 @@ void func_8000F628(void) { copy_courses_kart_ai_behaviour(); } -extern TrackWaypoint test_course_path[17]; - // @arg index from 0 to 3. // Processes course path by index. @@ -3680,26 +3654,12 @@ void func_800100F0(s32 pathIndex) { pathDest = D_80164550[pathIndex]; bInvalidPath = 1; if (GetCourse() != GetPodiumCeremony()) { - - if (GetCourse() == GetTestCourse()) { - var_v0 = process_path_data(pathDest, test_course_path); - gWaypointCountByPathIndex[pathIndex] = (u16) var_v0; - } else { - - var_v0 = process_path_data(pathDest, LOAD_ASSET(CourseManager_GetProps()->PathTable2[pathIndex])); - gWaypointCountByPathIndex[pathIndex] = (u16) var_v0; - } - } - - else { + var_v0 = process_path_data(pathDest, CourseManager_GetProps()->PathTable2[pathIndex]); + gWaypointCountByPathIndex[pathIndex] = (u16) var_v0; + } else { // Course path included in course_data which has already been loaded into memory. // This is how we get the addr to our path data. - - if (GetCourse() == GetTestCourse()) { - path = test_course_path; - } else { - path = LOAD_ASSET(CourseManager_GetProps()->PathTable[pathIndex]); - } + path = CourseManager_GetProps()->PathTable[pathIndex]; ptr = path; for (i = 0; i < 3000; i++, ptr++) { @@ -4204,10 +4164,10 @@ void kart_ai_behaviour_start(s32 playerId, Player* player) { s32 behaviourType; UNUSED s32 test; - KartAIBehaviour* beh = (KartAIBehaviour*) LOAD_ASSET(CourseManager_GetProps()->AIBehaviour); + KartAIBehaviour *beh = (KartAIBehaviour*)LOAD_ASSET(CourseManager_GetProps()->AIBehaviour); - sCurrentKartAIBehaviour = - &((KartAIBehaviour*) LOAD_ASSET(CourseManager_GetProps()->AIBehaviour))[gCurrentKartAIBehaviourId[playerId]]; + sCurrentKartAIBehaviour = + &((KartAIBehaviour*)LOAD_ASSET(CourseManager_GetProps()->AIBehaviour))[gCurrentKartAIBehaviourId[playerId]]; playerWaypoint = gNearestWaypointByPlayerId[playerId]; @@ -4359,10 +4319,10 @@ void func_80011EC0(s32 arg0, Player* player, s32 arg2, UNUSED u16 arg3) { } \ } -void generate_train_waypoints(const char* path) { +void generate_train_waypoints(void) { s32 i; Path2D* temp; - TrackWaypoint* waypoint = (TrackWaypoint*) LOAD_ASSET(path); + TrackWaypoint* waypoint = (TrackWaypoint*) LOAD_ASSET(d_course_kalimari_desert_track_unknown_waypoints); GET_PATH_LENGTH(waypoint) temp = gVehicle2DWaypoint; @@ -4382,28 +4342,28 @@ void generate_ferry_waypoints(void) { D_80162EB2 = -40; } -void spawn_vehicle_on_road(VehicleStuff* vehicle) { +void spawn_vehicle_on_road(Vec3f position, Vec3s rotation, Vec3f velocity, s32 waypointIndex, s32 someMultiplierTheSequel, f32 speed) { f32 origXPos; UNUSED f32 pad; f32 origZPos; - origXPos = vehicle->position[0]; - origZPos = vehicle->position[2]; + origXPos = position[0]; + origZPos = position[2]; if (D_8016347A == 0) { - func_8000D6D0(vehicle->position, (s16*) &vehicle->waypointIndex, vehicle->speed, - vehicle->someMultiplierTheSequel, 0, 3); - vehicle->rotation[0] = 0; - vehicle->rotation[1] = -0x8000; - vehicle->rotation[2] = 0; + func_8000D6D0(position, (s16*) &waypointIndex, speed, + someMultiplierTheSequel, 0, 3); + rotation[0] = 0; + rotation[1] = -0x8000; + rotation[2] = 0; } else { - func_8000D940(vehicle->position, (s16*) &vehicle->waypointIndex, vehicle->speed, - vehicle->someMultiplierTheSequel, 0); - vehicle->rotation[0] = 0; - vehicle->rotation[1] = 0; - vehicle->rotation[2] = 0; + func_8000D940(position, (s16*) &waypointIndex, speed, + someMultiplierTheSequel, 0); + rotation[0] = 0; + rotation[1] = 0; + rotation[2] = 0; } - vehicle->velocity[0] = vehicle->position[0] - origXPos; - vehicle->velocity[2] = vehicle->position[2] - origZPos; + velocity[0] = position[0] - origXPos; + velocity[2] = position[2] - origZPos; } void spawn_course_vehicles(void) { @@ -4425,6 +4385,34 @@ void spawn_course_vehicles(void) { f32 origZPos; CourseManager_SpawnVehicles(); + + // if (GetCourse() == GetToadsTurnpike()) { + // for (loopIndex = 0; loopIndex < NUM_RACE_BOX_TRUCKS; loopIndex++) { + // tempBoxTruck = &gBoxTruckList[loopIndex]; + // spawn_vehicle_on_road(tempBoxTruck); + // tempBoxTruck->actorIndex = add_actor_to_empty_slot(tempBoxTruck->position, tempBoxTruck->rotation, + // tempBoxTruck->velocity, ACTOR_BOX_TRUCK); + // } + // for (loopIndex = 0; loopIndex < NUM_RACE_SCHOOL_BUSES; loopIndex++) { + // tempSchoolBus = &gSchoolBusList[loopIndex]; + // spawn_vehicle_on_road(tempSchoolBus); + // tempSchoolBus->actorIndex = add_actor_to_empty_slot(tempSchoolBus->position, tempSchoolBus->rotation, + // tempSchoolBus->velocity, ACTOR_SCHOOL_BUS); + // } + // for (loopIndex = 0; loopIndex < NUM_RACE_TANKER_TRUCKS; loopIndex++) { + // tempTankerTruck = &gTankerTruckList[loopIndex]; + // spawn_vehicle_on_road(tempTankerTruck); + // tempTankerTruck->actorIndex = + // add_actor_to_empty_slot(tempTankerTruck->position, tempTankerTruck->rotation, + // tempTankerTruck->velocity, ACTOR_TANKER_TRUCK); + // } + // for (loopIndex = 0; loopIndex < NUM_RACE_CARS; loopIndex++) { + // tempCar = &gCarList[loopIndex]; + // spawn_vehicle_on_road(tempCar); + // tempCar->actorIndex = + // add_actor_to_empty_slot(tempCar->position, tempCar->rotation, tempCar->velocity, ACTOR_CAR); + // } + // } } void set_vehicle_pos_waypoint(TrainCarStuff* trainCar, Path2D* posXZ, u16 waypoint) { @@ -4450,14 +4438,12 @@ void init_vehicles_trains(size_t i, size_t numCarriages, f32 speed) { Path2D* pos; s32 j; - gNumTrains += 1; - gTrainList[i].numCarriages = numCarriages; - // for (i = 0; i < NUM_TRAINS; i++) { - // outputs 160 or 392 depending on the train. - // Wraps the value around to always output a valid waypoint. - waypointOffset = (((i * gVehicle2DWaypointLength) / gNumTrains) + 160) % gVehicle2DWaypointLength; + //for (i = 0; i < NUM_TRAINS; i++) { + // outputs 160 or 392 depending on the train. + // Wraps the value around to always output a valid waypoint. + waypointOffset = (((i * gVehicle2DWaypointLength) / 2) + 160) % gVehicle2DWaypointLength; // 120.0f is about the maximum usable value gTrainList[i].speed = speed; @@ -4546,7 +4532,7 @@ void update_vehicle_trains(void) { gTrainSmokeTimer += 1; - for (i = 0; i < gNumTrains; i++) { + for (i = 0; i < NUM_TRAINS; i++) { oldWaypointIndex = (u16) gTrainList[i].locomotive.waypointIndex; temp_f20 = gTrainList[i].locomotive.position[0]; @@ -4622,7 +4608,7 @@ void func_80012DC0(s32 playerId, Player* player) { if (!(player->effects & 0x01000000)) { playerPosX = player->pos[0]; playerPosZ = player->pos[2]; - for (trainIndex = 0; trainIndex < gNumTrains; trainIndex++) { + for (trainIndex = 0; trainIndex < NUM_TRAINS; trainIndex++) { trainCar = &gTrainList[trainIndex].locomotive; x_dist = playerPosX - trainCar->position[0]; z_dist = playerPosZ - trainCar->position[2]; @@ -4675,7 +4661,7 @@ void func_80013054(void) { isCrossingTriggeredByIndex[0] = 0; isCrossingTriggeredByIndex[1] = 0; - for (i = 0; i < gNumTrains; i++) { + for (i = 0; i < NUM_TRAINS; i++) { temp_f16 = gTrainList[i].locomotive.waypointIndex / ((f32) gVehicle2DWaypointLength); temp_f18 = 0.72017354f; temp_f12 = 0.42299348f; diff --git a/src/code_80005FD0.h b/src/code_80005FD0.h index 338292918..1976cb8ae 100644 --- a/src/code_80005FD0.h +++ b/src/code_80005FD0.h @@ -154,7 +154,7 @@ void func_80011EC0(s32, Player*, s32, u16); void generate_train_waypoints(const char*); void generate_ferry_waypoints(void); -void spawn_vehicle_on_road(VehicleStuff*); +void spawn_vehicle_on_road(Vec3f position, Vec3s rotation, Vec3f velocity, s32 waypointIndex, s32 someMultiplierTheSequel, f32 speed); void spawn_course_vehicles(void); void set_vehicle_pos_waypoint(TrainCarStuff*, Path2D*, u16); void init_vehicles_trains(size_t, size_t, f32); diff --git a/src/code_80057C60.c b/src/code_80057C60.c index a0c676010..a359e1dcd 100644 --- a/src/code_80057C60.c +++ b/src/code_80057C60.c @@ -696,6 +696,7 @@ void render_player_snow_effect_four(void) { void render_object_for_player(s32 cameraId) { CourseManager_RenderCourseObjects(cameraId); + CourseManager_TrainSmokeDraw(cameraId); // switch (gCurrentCourseId) { // case COURSE_MARIO_RACEWAY: @@ -1570,6 +1571,7 @@ void func_8005A71C(void) { void update_object(void) { CourseManager_UpdateCourseObjects(); + CourseManager_TrainSmokeTick(); // switch (gCurrentCourseId) { // case COURSE_MARIO_RACEWAY: diff --git a/src/code_8006E9C0.c b/src/code_8006E9C0.c index c3b0c2322..3a31a3ef2 100644 --- a/src/code_8006E9C0.c +++ b/src/code_8006E9C0.c @@ -29,6 +29,9 @@ #include #include "port/Game.h" +#include "engine/Engine.h" +#include "engine/courses/Course.h" + void init_hud(void) { reset_object_variable(); @@ -159,11 +162,12 @@ void init_item_window(s32 objectIndex) { } void func_8006EEE8(s32 courseId) { - D_8018D240 = (uintptr_t) dma_textures(gCourseOutlineTextures[courseId], D_800E5520[courseId], D_800E5520[courseId]); + D_8018D240 = (uintptr_t) dma_textures(CourseManager_GetProps()->MinimapTexture, D_800E5520[courseId], + ResourceGetTexSizeByName(CourseManager_GetProps()->MinimapTexture)); // This is incredibly dumb. D_800E5548 ought to be something more like // `u16 D_800E5548[][2]` but that doesn't match for some insane reason - D_8018D2B0 = D_800E5548[courseId * 2]; - D_8018D2B8 = D_800E5548[courseId * 2 + 1]; + D_8018D2B0 = CourseManager_GetProps()->D_800E5548[0]; // D_800E5548[courseId * 2]; + D_8018D2B8 = CourseManager_GetProps()->D_800E5548[1]; // D_800E5548[courseId * 2 + 1]; } void func_8006EF60(void) { @@ -175,7 +179,7 @@ void func_8006EF60(void) { wut = D_8018D9B4 + 0xFFFF0000; // clang-format off // God forgive me for my sins... - huh = 0x14; if (0) {} for (i = 0; i < huh; i++) { D_8018D248[i] = func_8006ED94(gCourseOutlineTextures[i], wut, D_800E5520[i], D_800E5520[i]); wut += D_800E5520[i]; } + huh = 0x14; if (0) {} for (i = 0; i < huh; i++) { D_8018D248[i] = func_8006ED94(CourseManager_GetProps()->MinimapTexture, wut, ResourceGetTexSizeByName(CourseManager_GetProps()->MinimapTexture), D_800E5520[i]); wut += D_800E5520[i]; } // clang-format on } diff --git a/src/code_80091750.c b/src/code_80091750.c index 9522a57bb..def1f448e 100644 --- a/src/code_80091750.c +++ b/src/code_80091750.c @@ -76,8 +76,7 @@ struct_8018E768_entry D_8018E768[D_8018E768_SIZE]; s32 gCycleFlashMenu; s8 D_8018E7AC[5]; u32 D_8018E7B8[5]; -u32 D_8018E7D0[4]; -s32 D_8018E7E0; +u32 D_8018E7D0[5]; struct UnkStruct_8018E7E8 D_8018E7E8[D_8018E7E8_SIZE]; struct UnkStruct_8018E7E8 D_8018E810[D_8018E810_SIZE]; s8 D_8018E838[4]; // Import to C was required for matching. diff --git a/src/engine/Cup.cpp b/src/engine/Cup.cpp index 0e77ac9b8..edbc0ebbd 100644 --- a/src/engine/Cup.cpp +++ b/src/engine/Cup.cpp @@ -22,6 +22,13 @@ void Cup::Previous() { } } +void Cup::SetCourse(size_t position) { + if ((position < 0) || (position >= Courses.size())) { + throw std::invalid_argument("Invalid course index."); + } + CursorPosition = position; +} + Course* Cup::GetCourse() { return Courses[CursorPosition]; } diff --git a/src/engine/Cup.h b/src/engine/Cup.h index bd064a7a9..c029cecd5 100644 --- a/src/engine/Cup.h +++ b/src/engine/Cup.h @@ -20,6 +20,7 @@ public: virtual void Next(); virtual void Previous(); + virtual void SetCourse(size_t position); virtual Course* GetCourse(); virtual size_t GetSize(); }; \ No newline at end of file diff --git a/src/engine/Engine.h b/src/engine/Engine.h index 497ee33b7..9a220c1a4 100644 --- a/src/engine/Engine.h +++ b/src/engine/Engine.h @@ -5,6 +5,7 @@ #include "bomb_kart.h" #include "objects.h" #include "path_spawn_metadata.h" +#include "waypoints.h" typedef struct { RGB8 TopRight; @@ -23,6 +24,8 @@ typedef struct { const char* DebugName; const char* CourseLength; const char* AIBehaviour; + const char* MinimapTexture; + s16 D_800E5548[2]; float AIMaximumSeparation; float AIMinimumSeparation; float NearPersp; @@ -34,8 +37,8 @@ typedef struct { Vec4f D_0D009568; Vec4f D_0D0096B8; Vec4f D_0D009808; - const char* PathTable[4]; - const char* PathTable2[4]; + TrackWaypoint* PathTable[4]; + TrackWaypoint* PathTable2[4]; CloudData *Clouds; CloudData *CloudList; s32 MinimapFinishlineX; diff --git a/src/engine/GameObject.cpp b/src/engine/GameObject.cpp index 691ec9e13..371d85073 100644 --- a/src/engine/GameObject.cpp +++ b/src/engine/GameObject.cpp @@ -19,6 +19,3 @@ void GameObject::Render(Camera* camera) { } void GameObject::Collision() {} void GameObject::Expire() { } void GameObject::Destroy() { } -// World* GameObject::GetWorld() { -// // return &gWorldInstance; -// } \ No newline at end of file diff --git a/src/engine/Smoke.cpp b/src/engine/Smoke.cpp new file mode 100644 index 000000000..9d74397dc --- /dev/null +++ b/src/engine/Smoke.cpp @@ -0,0 +1,109 @@ +#include +#include + +#include "Smoke.h" +#include "World.h" +#include "vehicles/Vehicle.h" +#include "vehicles/Train.h" +#include "vehicles/Boat.h" + +extern "C" { +#include "macros.h" +#include "render_objects.h" +#include "code_80057C60.h" +#include "update_objects.h" +#include "math_util_2.h" +#include "assets/common_data.h" +} + +//! @todo: This should be an Object class one day +void TrainSmokeTick() { + s32 count; + s32 i; + s32 temp_a0; + Object* object; + + for (auto& vehicle : gWorldInstance.Vehicles) { + if (auto train = dynamic_cast(vehicle.get())) { + if (train->SmokeTimer != 0) { + train->SmokeTimer -= 1; + } + + if ((train->SomeFlags != 0) || (train->SmokeTimer != 0)) { + count = 0; + for (i = 0; i < 128; i++) { + temp_a0 = train->SmokeParticles[i]; + if (temp_a0 != -1) { + object = &gObjectList[temp_a0]; + if (object->state != 0) { + func_80075714(temp_a0); + if (object->state == 0) { + delete_object_wrapper(&train->SmokeParticles[i]); + } + count += 1; + } + } + } + if (count != 0) { + train->SmokeTimer = 100; + } + } + } else if (auto boat = dynamic_cast(vehicle.get())) { + if (boat->SmokeTimer != 0) { + boat->SmokeTimer -= 1; + } + if ((boat->SomeFlags != 0) || (boat->SmokeTimer != 0)) { + count = 0; + for (size_t i = 0; i < 128; i++) { + temp_a0 = boat->SmokeParticles[i]; + if (temp_a0 != -1) { + object = &gObjectList[temp_a0]; + if (object->state != 0) { + func_80075B84(temp_a0); + if (object->state == 0) { + delete_object_wrapper(&boat->SmokeParticles[i]); + } + count += 1; + } + } + } + if (count != 0) { + boat->SmokeTimer = 100; + } + + } + } + } +} + +void TrainSmokeDraw(s32 cameraId) { + Camera* camera = &camera1[cameraId]; + for (auto& vehicle : gWorldInstance.Vehicles) { + if (auto train = dynamic_cast(vehicle.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); + D_80183E80[0] = 0; + D_80183E80[2] = 0x8000; + + if ((train->SomeFlags != 0) && + (is_particle_on_screen(train->Locomotive.position, camera, 0x4000U) != 0)) { + for (size_t i = 0; i < 128; i++) { + render_object_train_smoke_particle(train->SmokeParticles[i], cameraId); + } + } + } else if (auto boat = dynamic_cast(vehicle.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); + D_80183E80[0] = 0; + D_80183E80[2] = 0x8000; + if ((boat->SomeFlags != 0) && (is_particle_on_screen(boat->Position, camera, 0x4000U) != 0)) { + for (size_t i = 0; i < gObjectParticle2_SIZE; i++) { + render_object_paddle_boat_smoke_particle(boat->SmokeParticles[i], cameraId); + } + } + } + } +} diff --git a/src/engine/Smoke.h b/src/engine/Smoke.h new file mode 100644 index 000000000..4fbafead0 --- /dev/null +++ b/src/engine/Smoke.h @@ -0,0 +1,7 @@ +#ifndef _ENGINE_SMOKE_H +#define _ENGINE_SMOKE_H + +void TrainSmokeTick(void); +void TrainSmokeDraw(s32 cameraId); + +#endif // _ENGINE_SMOKE_H diff --git a/src/engine/TrainCrossing.cpp b/src/engine/TrainCrossing.cpp new file mode 100644 index 000000000..3216e7945 --- /dev/null +++ b/src/engine/TrainCrossing.cpp @@ -0,0 +1,89 @@ +#include +#include "TrainCrossing.h" +#include "World.h" +#include "vehicles/Vehicle.h" +#include "vehicles/Train.h" +#include + +extern "C" { +#include "macros.h" +#include "main.h" +#include "vehicles.h" +#include "code_80005FD0.h" +#include "common_structs.h" +} + +TrainCrossing::TrainCrossing(Vec3f position, u32 waypointMin, u32 waypointMax, f32 approachRadius, f32 exitRadius) { + Position[0] = position[0]; + Position[1] = position[1]; + Position[2] = position[2]; + ApproachRadius = approachRadius; + ExitRadius = exitRadius; + WaypointMin = waypointMin; + WaypointMax = waypointMax; +} + +void TrainCrossing::CrossingTrigger() { + f32 waypoint; + s32 i; + OnTriggered = 0; + + + for (const auto& vehicle : gWorldInstance.Vehicles) { + if (auto train = dynamic_cast(vehicle.get())) {; + f32 radius = DynamicRadius(train->Locomotive.position, train->Locomotive.velocity, Position); + + if (Distance(train->Locomotive.position, Position) < radius) { + OnTriggered = true; // Trigger within range + } + } + } + + if (OnTriggered) { + Timer += 1; + } else { + Timer = 0; + } +} + +void TrainCrossing::AICrossingBehaviour(s32 playerId) { + bStopAICrossing[playerId] = 0; + + if ((!(D_801631E0[playerId] != 0)) || + (set_vehicle_render_distance_flags(gPlayers[playerId].pos, TRAIN_CROSSING_AI_DISTANCE, 0))) { + if ((OnTriggered == 1) && ((Timer) > FRAMES_SINCE_CROSSING_ACTIVATED)) { + if ((sSomeNearestWaypoint > WaypointMin) && (sSomeNearestWaypoint < WaypointMax)) { + printf("STOP AI\n"); + bStopAICrossing[playerId] = 1; + } + } + } +} + +f32 TrainCrossing::Distance(Vec3f a, Vec3f b) { + float dx = b[0] - a[0]; // Difference in x-coordinates + float dy = b[1] - a[1]; // Difference in y-coordinates + float dz = b[2] - a[2]; // Difference in z-coordinates + return sqrt(dx * dx + dy * dy + dz * dz); // Return the distance +} + +f32 TrainCrossing::DynamicRadius(Vec3f trainPos, Vec3f trainVelocity, Vec3f crossingPos) { + // Calculate direction of train (this assumes velocity is a normalized direction vector) + Vec3f trainToCrossing; + trainToCrossing[0] = crossingPos[0] - trainPos[0]; + trainToCrossing[1] = crossingPos[1] - trainPos[1]; + trainToCrossing[2] = crossingPos[2] - trainPos[2]; + + // Dot product to check if the train is approaching or moving away from the crossing + f32 dotProduct = trainToCrossing[0] * trainVelocity[0] + + trainToCrossing[1] * trainVelocity[1] + + trainToCrossing[2] * trainVelocity[2]; + + if (dotProduct > 0) { + // Train is approaching the crossing + return ApproachRadius; + } else { + // Train has passed the crossing + return ExitRadius; + } +} diff --git a/src/engine/TrainCrossing.h b/src/engine/TrainCrossing.h new file mode 100644 index 000000000..eeb6b5fc2 --- /dev/null +++ b/src/engine/TrainCrossing.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +extern "C" { +#include "common_structs.h" +} + +/** + * @brief TrainCrossing class + * @arg Vec3f position of the crossing + * @arg u32 waypointMin + * @arg u32 waypointMax + * + * Min/Max are used to determine the range for AI to stop for the crossing. + * + */ +class TrainCrossing { +public: + TrainCrossing(Vec3f position, u32 waypointMin, u32 waypointMax, f32 approachRadius, f32 exitRadius); + + Vec3f Position; + s32 OnTriggered = 0; + u32 Timer; + u32 WaypointMin; + u32 WaypointMax; + + f32 ApproachRadius; + f32 ExitRadius; + + virtual void CrossingTrigger(); + virtual void AICrossingBehaviour(s32 playerId); + f32 Distance(Vec3f a, Vec3f b); + f32 DynamicRadius(Vec3f trainPos, Vec3f trainVelocity, Vec3f crossingPos); +}; diff --git a/src/engine/World.cpp b/src/engine/World.cpp index 05a725aff..a27ee2540 100644 --- a/src/engine/World.cpp +++ b/src/engine/World.cpp @@ -2,6 +2,16 @@ #include "World.h" #include "Cup.h" #include "courses/Course.h" +#include "vehicles/Vehicle.h" +#include "vehicles/Train.h" +#include "vehicles/Boat.h" +#include "vehicles/Truck.h" +#include "vehicles/Bus.h" +#include "vehicles/TankerTruck.h" +#include "vehicles/Car.h" +#include "TrainCrossing.h" +#include + extern "C" { #include "camera.h" @@ -38,6 +48,54 @@ void World::SetCourseFromCup() { CurrentCourse = CurrentCup->GetCourse(); } +// Required for spawning vehicles in divisions across path points +static size_t trains; +static size_t trucks; +static size_t busses; +static size_t tankerTrucks; +static size_t cars; +static size_t boats; +void World::AddTrain(size_t numCarriages, f32 speed, uint32_t waypoint) { + Vehicles.push_back(std::make_unique(trains, numCarriages, speed, waypoint)); + trains++; +} + +void World::AddBoat(f32 speed, uint32_t waypoint) { + Vehicles.push_back(std::make_unique(boats, speed, waypoint)); + boats++; +} + +void World::AddTruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) { + Vehicles.push_back(std::make_unique(trucks, speedA, speedB, path, waypoint)); + trucks++; +} + +void World::AddBus(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) { + Vehicles.push_back(std::make_unique(busses, speedA, speedB, path, waypoint)); + busses++; +} + +void World::AddTankerTruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) { + Vehicles.push_back(std::make_unique(tankerTrucks, speedA, speedB, path, waypoint)); + tankerTrucks++; +} + +void World::AddCar(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) { + Vehicles.push_back(std::make_unique(cars, speedA, speedB, path, waypoint)); + cars++; +} + +void World::ResetVehicles(void) { + trains = trucks = busses = tankerTrucks = cars = boats = 0; + Vehicles.clear(); +} + +TrainCrossing* World::AddCrossing(Vec3f position, u32 waypointMin, u32 waypointMax, f32 approachRadius, f32 exitRadius) { + auto crossing = std::make_shared(position, waypointMin, waypointMax, approachRadius, exitRadius); + Crossings.push_back(crossing); + return crossing.get(); +} + //const char* World::GetCupName() { // //return this->Cups[CupIndex].Name; //} diff --git a/src/engine/World.h b/src/engine/World.h index 45edd7646..8b99d796a 100644 --- a/src/engine/World.h +++ b/src/engine/World.h @@ -3,6 +3,11 @@ #include #include "GameObject.h" #include "Cup.h" +#include "vehicles/Vehicle.h" +#include "vehicles/Train.h" +#include "vehicles/Car.h" +#include "TrainCrossing.h" +#include extern "C" { #include "camera.h" @@ -12,6 +17,10 @@ extern "C" { class Cup; // <-- Forward declaration class Course; +class AVehicle; +class ATrain; +class ACar; +class TrainCrossing; class World { @@ -81,7 +90,7 @@ public: virtual void SetCourseFromCup(); void SetCup(); - World* GetWorld(); + World* GetWorld(void); // These are only for browsing through the course list @@ -100,6 +109,18 @@ public: std::vector> GameObjects; // std::vector> GameActors; + void AddBoat(f32 speed, uint32_t waypoint); + void AddTrain(size_t numCarriages, f32 speed, uint32_t waypoint); + void AddTruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint); + void AddBus(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint); + void AddTankerTruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint); + void AddCar(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint); + std::vector> Vehicles; + void ResetVehicles(void); + + TrainCrossing* AddCrossing(Vec3f position, u32 waypointMin, u32 waypointMax, f32 approachRadius, f32 exitRadius); + std::vector> Crossings; + std::vector Courses; size_t CourseIndex = 0; // For browsing courses. private: @@ -107,4 +128,3 @@ private: }; extern World gWorldInstance; - diff --git a/src/engine/courses/BansheeBoardwalk.cpp b/src/engine/courses/BansheeBoardwalk.cpp index 854d2d3ab..c54f94f35 100644 --- a/src/engine/courses/BansheeBoardwalk.cpp +++ b/src/engine/courses/BansheeBoardwalk.cpp @@ -38,6 +38,9 @@ BansheeBoardwalk::BansheeBoardwalk() { this->gfx = d_course_banshee_boardwalk_packed_dls; this->gfxSize = 3689; this->textures = banshee_boardwalk_textures; + Props.MinimapTexture = gTextureCourseOutlineBansheeBoardwalk; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Id = "mk:banshee_boardwalk"; Props.Name = "banshee boardwalk"; @@ -74,12 +77,12 @@ BansheeBoardwalk::BansheeBoardwalk() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_banshee_boardwalk_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_banshee_boardwalk_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_banshee_boardwalk_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_banshee_boardwalk_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -103,7 +106,7 @@ void BansheeBoardwalk::LoadTextures() { } void BansheeBoardwalk::SpawnActors() { - spawn_all_item_boxes(d_course_banshee_boardwalk_item_box_spawns); + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_banshee_boardwalk_item_box_spawns)); } void BansheeBoardwalk::Init() { } @@ -188,17 +191,13 @@ void BansheeBoardwalk::WhatDoesThisDoAI(Player* player, int8_t playerId) { } void BansheeBoardwalk::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(140, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(165, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(330, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(550, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(595, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(140, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(165, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(330, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(550, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(595, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -282,7 +281,7 @@ void BansheeBoardwalk::GenerateCollision() { D_801625EC = 0; D_801625F4 = 0; D_801625F0 = 0; - parse_course_displaylists(d_course_banshee_boardwalk_track_sections); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_banshee_boardwalk_track_sections)); func_80295C6C(); find_vtx_and_set_colours(segmented_gfx_to_virtual(reinterpret_cast(0x07000878)), 128, 0, 0, 0); D_8015F8E4 = -80.0f; diff --git a/src/engine/courses/BigDonut.cpp b/src/engine/courses/BigDonut.cpp index 581472ca1..daca979c0 100644 --- a/src/engine/courses/BigDonut.cpp +++ b/src/engine/courses/BigDonut.cpp @@ -38,6 +38,9 @@ BigDonut::BigDonut() { this->gfx = d_course_big_donut_packed_dls; this->gfxSize = 528; this->textures = big_donut_textures; + Props.MinimapTexture = gTextureCourseOutlineBigDonut; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Name = "big donut"; Props.DebugName = "doughnut"; diff --git a/src/engine/courses/BlockFort.cpp b/src/engine/courses/BlockFort.cpp index fad4eceda..27ac81305 100644 --- a/src/engine/courses/BlockFort.cpp +++ b/src/engine/courses/BlockFort.cpp @@ -38,6 +38,9 @@ BlockFort::BlockFort() { this->gfx = d_course_block_fort_packed_dls; this->gfxSize = 699; this->textures = block_fort_textures; + Props.MinimapTexture = gTextureCourseOutlineBlockFort; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Name = "block fort"; Props.DebugName = "block"; diff --git a/src/engine/courses/BowsersCastle.cpp b/src/engine/courses/BowsersCastle.cpp index 33179e739..544d7f1d6 100644 --- a/src/engine/courses/BowsersCastle.cpp +++ b/src/engine/courses/BowsersCastle.cpp @@ -28,6 +28,7 @@ extern "C" { #include "staff_ghosts.h" #include "actors.h" #include "collision.h" + #include "code_8003DC40.h" #include "memory.h" extern const char *bowsers_castle_dls[]; } @@ -37,6 +38,9 @@ BowsersCastle::BowsersCastle() { this->gfx = d_course_bowsers_castle_packed_dls; this->gfxSize = 4900; this->textures = bowsers_castle_textures; + Props.MinimapTexture = gTextureCourseOutlineBowsersCastle; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Id = "mk:bowsers_castle"; Props.Name = "bowser's castle"; @@ -73,12 +77,12 @@ BowsersCastle::BowsersCastle() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_bowsers_castle_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_bowsers_castle_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_bowsers_castle_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_bowsers_castle_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -103,8 +107,8 @@ void BowsersCastle::LoadTextures() { } void BowsersCastle::SpawnActors() { - spawn_foliage(d_course_bowsers_castle_tree_spawn); - spawn_all_item_boxes(d_course_bowsers_castle_item_box_spawns); + 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)); } void BowsersCastle::Init() { } @@ -211,17 +215,13 @@ void BowsersCastle::WhatDoesThisDoAI(Player* player, int8_t playerId) { } void BowsersCastle::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(140, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(165, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(330, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(550, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(595, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(140, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(165, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(330, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(550, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(595, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -267,8 +267,12 @@ void BowsersCastle::RenderCredits() { void BowsersCastle::Collision() {} +void BowsersCastle::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) { + func_8003E6EC(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7); +} + void BowsersCastle::GenerateCollision() { - parse_course_displaylists(d_course_bowsers_castle_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_bowsers_castle_addr)); func_80295C6C(); find_vtx_and_set_colours(segmented_gfx_to_virtual(reinterpret_cast(0x07001350)), 0x32, 0, 0, 0); D_8015F8E4 = -50.0f; diff --git a/src/engine/courses/BowsersCastle.h b/src/engine/courses/BowsersCastle.h index f949303c2..2c00d6e80 100644 --- a/src/engine/courses/BowsersCastle.h +++ b/src/engine/courses/BowsersCastle.h @@ -39,8 +39,9 @@ public: virtual void SetStaffGhost() override; virtual void BeginPlay() override; virtual void Render(struct UnkStruct_800DC5EC*) override; - virtual void RenderCredits() override; + virtual void RenderCredits() override; virtual void Collision() override; + virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override; virtual void SpawnBombKarts() override; virtual void GenerateCollision() override; virtual void Waypoints(Player*, int8_t) override; diff --git a/src/engine/courses/ChocoMountain.cpp b/src/engine/courses/ChocoMountain.cpp index f2f008fba..aad4d8d3d 100644 --- a/src/engine/courses/ChocoMountain.cpp +++ b/src/engine/courses/ChocoMountain.cpp @@ -28,6 +28,7 @@ extern "C" { #include "staff_ghosts.h" #include "actors.h" #include "collision.h" + #include "code_8003DC40.h" #include "memory.h" extern const char *choco_mountain_dls[]; } @@ -37,6 +38,9 @@ ChocoMountain::ChocoMountain() { this->gfx = d_course_choco_mountain_packed_dls; this->gfxSize = 2910; this->textures = choco_mountain_textures; + Props.MinimapTexture = gTextureCourseOutlineChocoMountain; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Id = "mk:choco_mountain"; Props.Name = "choco mountain"; @@ -73,12 +77,12 @@ ChocoMountain::ChocoMountain() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_choco_mountain_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_choco_mountain_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_choco_mountain_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_choco_mountain_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -102,8 +106,8 @@ void ChocoMountain::LoadTextures() { } void ChocoMountain::SpawnActors() { - spawn_all_item_boxes(d_course_choco_mountain_item_box_spawns); - spawn_falling_rocks(d_course_choco_mountain_falling_rock_spawns); + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_choco_mountain_item_box_spawns)); + spawn_falling_rocks((struct ActorSpawnData*)LOAD_ASSET_RAW((const char*)d_course_choco_mountain_falling_rock_spawns)); } void ChocoMountain::Init() { } @@ -164,17 +168,13 @@ void ChocoMountain::WhatDoesThisDoAI(Player* player, int8_t playerId) { } void ChocoMountain::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(140, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(165, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(330, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(550, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(595, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(140, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(165, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(330, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(550, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(595, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -240,6 +240,10 @@ void ChocoMountain::RenderCredits() { void ChocoMountain::Collision() {} +void ChocoMountain::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) { + func_8003E37C(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7); +} + void ChocoMountain::GenerateCollision() { D_800DC5BC = 1; D_801625EC = 255; @@ -266,7 +270,7 @@ void ChocoMountain::GenerateCollision() { nullify_displaylist((uintptr_t) segmented_gfx_to_virtual(reinterpret_cast(0x070003C8))); } - parse_course_displaylists(d_course_choco_mountain_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_choco_mountain_addr)); func_802B5CAC(0x238E, 0x31C7, D_8015F590); func_80295C6C(); D_8015F8E4 = -80.0f; diff --git a/src/engine/courses/ChocoMountain.h b/src/engine/courses/ChocoMountain.h index c57f18e52..8bf07ffdf 100644 --- a/src/engine/courses/ChocoMountain.h +++ b/src/engine/courses/ChocoMountain.h @@ -39,6 +39,7 @@ public: virtual void Render(struct UnkStruct_800DC5EC*) override; virtual void RenderCredits() override; virtual void Collision() override; + virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override; virtual void SpawnBombKarts() override; virtual void GenerateCollision() override; virtual void Destroy() override; diff --git a/src/engine/courses/Course.cpp b/src/engine/courses/Course.cpp index b3f9248bb..8c6301dc1 100644 --- a/src/engine/courses/Course.cpp +++ b/src/engine/courses/Course.cpp @@ -147,6 +147,7 @@ void Course::UpdateClouds(s32 arg0, Camera* camera) { } } +// Adjusts player speed on steep hills void Course::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) { func_8003E048(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } @@ -197,12 +198,6 @@ void Course::SetStaffGhost() { } void Course::SpawnBombKarts() { -// GetWorld()->SpawnBombKarts(); -} - -World* Course::GetWorld() { - return nullptr; - //&gWorldInstance; } void Course::Waypoints(Player* player, int8_t playerId) { diff --git a/src/engine/courses/Course.h b/src/engine/courses/Course.h index bc817c73a..94f8fa3a7 100644 --- a/src/engine/courses/Course.h +++ b/src/engine/courses/Course.h @@ -17,6 +17,7 @@ extern "C" { #include "bomb_kart.h" #include "path_spawn_metadata.h" #include "Engine.h" + #include "waypoints.h" CProperties *CourseManager_GetProps(); @@ -54,6 +55,8 @@ public: const char* DebugName; const char* CourseLength; const char* AIBehaviour; + const char* MinimapTexture; + s16 D_800E5548[2]; float AIMaximumSeparation; float AIMinimumSeparation; float NearPersp; @@ -65,8 +68,8 @@ public: Vec4f D_0D009568; Vec4f D_0D0096B8; Vec4f D_0D009808; - const char* PathTable[4]; - const char* PathTable2[4]; + TrackWaypoint* PathTable[4]; + TrackWaypoint* PathTable2[4]; CloudData *Clouds; CloudData *CloudList; int32_t MinimapFinishlineX; @@ -81,15 +84,12 @@ public: size_t gfxSize = 0; const course_texture* textures = nullptr; - virtual ~Course() = default; // Virtual destructor for proper cleanup in derived classes + virtual ~Course() = default; - // Constructor - explicit Course(); // UUID should be passed in constructor + explicit Course(); - // Virtual functions to be overridden by derived classes - virtual void Load(); - virtual void Load(Vtx* vtx, Gfx *gfx); - // This function may not be needed due to otr system. + virtual void Load(); // Decompress and load stock courses. Must be overridden for custom courses + virtual void Load(Vtx* vtx, Gfx *gfx); // Load custom course virtual void LoadTextures(); virtual void SpawnActors(); virtual void Init(); @@ -117,8 +117,6 @@ public: virtual void GenerateCollision(); virtual void Water(); virtual void Destroy(); - virtual World* GetWorld(); - }; #endif diff --git a/src/engine/courses/DKJungle.cpp b/src/engine/courses/DKJungle.cpp index ba3842e6e..dc3dfa3f2 100644 --- a/src/engine/courses/DKJungle.cpp +++ b/src/engine/courses/DKJungle.cpp @@ -9,6 +9,8 @@ #include "BombKart.h" #include "assets/dks_jungle_parkway_data.h" +#include "engine/vehicles/Utils.h" + extern "C" { #include "main.h" #include "camera.h" @@ -28,6 +30,7 @@ extern "C" { #include "staff_ghosts.h" #include "actors.h" #include "collision.h" + #include "code_8003DC40.h" #include "memory.h" #include "sounds.h" extern const char *d_course_dks_jungle_parkway_unknown_dl_list[]; @@ -39,6 +42,9 @@ DKJungle::DKJungle() { this->gfx = d_course_dks_jungle_parkway_packed_dls; this->gfxSize = 4997; this->textures = dks_jungle_parkway_textures; + Props.MinimapTexture = gTextureCourseOutlineDksJungleParkway; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Name = "d.k.'s jungle parkway"; Props.DebugName = "jungle"; @@ -74,12 +80,12 @@ DKJungle::DKJungle() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_dks_jungle_parkway_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_dks_jungle_parkway_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_dks_jungle_parkway_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_dks_jungle_parkway_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -106,7 +112,7 @@ void DKJungle::LoadTextures() { } void DKJungle::SpawnActors() { - spawn_all_item_boxes(d_course_dks_jungle_parkway_item_box_spawns); + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_dks_jungle_parkway_item_box_spawns)); init_kiwano_fruit(); func_80298D10(); } @@ -190,17 +196,13 @@ void DKJungle::WhatDoesThisDoAI(Player* player, int8_t playerId) { } void DKJungle::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -241,48 +243,18 @@ void DKJungle::RenderCredits() { void DKJungle::Collision() {} -void DKJungle::SpawnVehicles() { - s16 trainCarYRot; - UNUSED Vec3f pad; - TrainCarStuff* tempLocomotive; - TrainCarStuff* tempTender; - TrainCarStuff* tempPassengerCar; - Vec3s trainCarRot; - VehicleStuff* tempBoxTruck; - VehicleStuff* tempSchoolBus; - VehicleStuff* tempTankerTruck; - VehicleStuff* tempCar; - PaddleBoatStuff* tempPaddleWheelBoat; - Vec3s paddleWheelBoatRot; - s32 loopIndex; - s32 loopIndex2; - f32 origXPos; - f32 origZPos; - - for (loopIndex = 0; loopIndex < NUM_ACTIVE_PADDLE_BOATS; loopIndex++) { - tempPaddleWheelBoat = &gPaddleBoats[loopIndex]; - if (tempPaddleWheelBoat->isActive == 1) { - origXPos = tempPaddleWheelBoat->position[0]; - origZPos = tempPaddleWheelBoat->position[2]; - tempPaddleWheelBoat->rotY = update_vehicle_following_waypoint( - tempPaddleWheelBoat->position, (s16*) &tempPaddleWheelBoat->waypointIndex, - tempPaddleWheelBoat->speed); - tempPaddleWheelBoat->velocity[0] = tempPaddleWheelBoat->position[0] - origXPos; - tempPaddleWheelBoat->velocity[2] = tempPaddleWheelBoat->position[2] - origZPos; - vec3s_set(paddleWheelBoatRot, 0, tempPaddleWheelBoat->rotY, 0); - tempPaddleWheelBoat->actorIndex = - add_actor_to_empty_slot(tempPaddleWheelBoat->position, paddleWheelBoatRot, - tempPaddleWheelBoat->velocity, ACTOR_PADDLE_BOAT); - } - } +void DKJungle::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) { + func_8003F138(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } -void DKJungle::UpdateVehicles() { - update_vehicle_paddle_boats(); +void DKJungle::SpawnVehicles() { + generate_ferry_waypoints(); + + gWorldInstance.AddBoat(1.6666666f, 0); } void DKJungle::GenerateCollision() { - parse_course_displaylists(d_course_dks_jungle_parkway_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_dks_jungle_parkway_addr)); func_80295C6C(); D_8015F8E4 = -475.0f; // d_course_dks_jungle_parkway_packed_dl_3FA8 diff --git a/src/engine/courses/DKJungle.h b/src/engine/courses/DKJungle.h index 747a7d738..e9b4af9ed 100644 --- a/src/engine/courses/DKJungle.h +++ b/src/engine/courses/DKJungle.h @@ -41,8 +41,8 @@ public: virtual void Render(struct UnkStruct_800DC5EC*) override; virtual void RenderCredits() override; virtual void SpawnVehicles() override; - virtual void UpdateVehicles() override; virtual void Collision() override; + virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override; virtual void SpawnBombKarts() override; virtual void GenerateCollision() override; virtual void Waypoints(Player* player, int8_t playerId) override; diff --git a/src/engine/courses/DoubleDeck.cpp b/src/engine/courses/DoubleDeck.cpp index 8dd3e1725..189dd3301 100644 --- a/src/engine/courses/DoubleDeck.cpp +++ b/src/engine/courses/DoubleDeck.cpp @@ -38,6 +38,9 @@ DoubleDeck::DoubleDeck() { this->gfx = d_course_double_deck_packed_dls; this->gfxSize = 699; this->textures = double_deck_textures; + Props.MinimapTexture = gTextureCourseOutlineDoubleDeck; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Name = "double deck"; Props.DebugName = "deck"; diff --git a/src/engine/courses/FrappeSnowland.cpp b/src/engine/courses/FrappeSnowland.cpp index 01b6a7cc4..a9da71586 100644 --- a/src/engine/courses/FrappeSnowland.cpp +++ b/src/engine/courses/FrappeSnowland.cpp @@ -40,6 +40,9 @@ FrappeSnowland::FrappeSnowland() { this->gfx = d_course_frappe_snowland_packed_dls; this->gfxSize = 4140; this->textures = frappe_snowland_textures; + Props.MinimapTexture = gTextureCourseOutlineFrappeSnowland; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Name = "frappe snowland"; Props.DebugName = "snow"; @@ -75,12 +78,12 @@ FrappeSnowland::FrappeSnowland() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_frappe_snowland_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_frappe_snowland_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_frappe_snowland_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_frappe_snowland_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -106,8 +109,8 @@ void FrappeSnowland::LoadTextures() { } void FrappeSnowland::SpawnActors() { - spawn_foliage(d_course_frappe_snowland_tree_spawns); - spawn_all_item_boxes(d_course_frappe_snowland_item_box_spawns); + 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)); } void FrappeSnowland::Init() { } @@ -186,17 +189,13 @@ void FrappeSnowland::WhatDoesThisDo(Player* player, int8_t playerId) {} void FrappeSnowland::WhatDoesThisDoAI(Player* player, int8_t playerId) {} void FrappeSnowland::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(140, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(165, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(330, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(550, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(595, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(140, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(165, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(330, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(550, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(595, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -234,7 +233,7 @@ void FrappeSnowland::RenderCredits() { void FrappeSnowland::Collision() {} void FrappeSnowland::GenerateCollision() { - parse_course_displaylists(d_course_frappe_snowland_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_frappe_snowland_addr)); func_80295C6C(); D_8015F8E4 = -50.0f; } diff --git a/src/engine/courses/KalimariDesert.cpp b/src/engine/courses/KalimariDesert.cpp index 625cba353..db155f91e 100644 --- a/src/engine/courses/KalimariDesert.cpp +++ b/src/engine/courses/KalimariDesert.cpp @@ -8,6 +8,9 @@ #include "World.h" #include "BombKart.h" #include "kalimari_desert_data.h" +#include "engine/vehicles/Utils.h" + +#include "engine/vehicles/Vehicle.h" extern "C" { #include "main.h" @@ -37,6 +40,9 @@ KalimariDesert::KalimariDesert() { this->gfx = d_course_kalimari_desert_packed_dls; this->gfxSize = 5328; this->textures = kalimari_desert_textures; + Props.MinimapTexture = gTextureCourseOutlineKalimariDesert; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 96; Props.Name = "kalimari desert"; Props.DebugName = "desert"; @@ -72,12 +78,12 @@ KalimariDesert::KalimariDesert() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_kalimari_desert_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_kalimari_desert_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_kalimari_desert_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_kalimari_desert_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -111,29 +117,35 @@ void KalimariDesert::SpawnActors() { Vec3f velocity = { 0.0f, 0.0f, 0.0f }; Vec3s rotation = { 0, 0, 0 }; - spawn_foliage(d_course_kalimari_desert_cactus_spawn); - spawn_all_item_boxes(d_course_kalimari_desert_item_box_spawns); + spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_kalimari_desert_cactus_spawn)); + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_kalimari_desert_item_box_spawns)); + + Vec3f crossingPos = {-2500, 2, 2355}; + Vec3f crossingPos2 = {-1639, 2, 68}; + uintptr_t* crossing1 = (uintptr_t*) gWorldInstance.AddCrossing(crossingPos, 306, 310, 900.0f, 650.0f); + uintptr_t* crossing2 = (uintptr_t*) gWorldInstance.AddCrossing(crossingPos2, 176, 182, 900.0f, 650.0f); + vec3f_set(position, -1680.0f, 2.0f, 35.0f); position[0] *= gCourseDirection; rrxing = (struct RailroadCrossing*) &gActorList[add_actor_to_empty_slot(position, rotation, velocity, ACTOR_RAILROAD_CROSSING)]; - rrxing->crossingId = 1; + rrxing->crossingTrigger = crossing2; vec3f_set(position, -1600.0f, 2.0f, 35.0f); position[0] *= gCourseDirection; rrxing = (struct RailroadCrossing*) &gActorList[add_actor_to_empty_slot(position, rotation, velocity, ACTOR_RAILROAD_CROSSING)]; - rrxing->crossingId = 1; + rrxing->crossingTrigger = crossing2; vec3s_set(rotation, 0, -0x2000, 0); vec3f_set(position, -2459.0f, 2.0f, 2263.0f); position[0] *= gCourseDirection; rrxing = (struct RailroadCrossing*) &gActorList[add_actor_to_empty_slot(position, rotation, velocity, ACTOR_RAILROAD_CROSSING)]; - rrxing->crossingId = 0; + rrxing->crossingTrigger = crossing1; vec3f_set(position, -2467.0f, 2.0f, 2375.0f); position[0] *= gCourseDirection; rrxing = (struct RailroadCrossing*) &gActorList[add_actor_to_empty_slot(position, rotation, velocity, ACTOR_RAILROAD_CROSSING)]; - rrxing->crossingId = 0; + rrxing->crossingTrigger = crossing1; } void KalimariDesert::Init() {} @@ -165,14 +177,6 @@ void KalimariDesert::InitCourseObjects() { } } -void KalimariDesert::UpdateCourseObjects() { - update_train_smoke(); -} - -void KalimariDesert::RenderCourseObjects(s32 cameraId) { - render_object_trains_smoke_particles(cameraId); -} - void KalimariDesert::SomeSounds() {} void KalimariDesert::WhatDoesThisDo(Player* player, int8_t playerId) {} @@ -180,17 +184,13 @@ void KalimariDesert::WhatDoesThisDo(Player* player, int8_t playerId) {} void KalimariDesert::WhatDoesThisDoAI(Player* player, int8_t playerId) {} void KalimariDesert::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(140, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(165, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(330, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(550, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(595, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(140, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(165, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(330, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(550, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(595, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -202,71 +202,19 @@ void KalimariDesert::MinimapFinishlinePosition() { void KalimariDesert::SetStaffGhost() {} void KalimariDesert::SpawnVehicles() { - s16 trainCarYRot; - UNUSED Vec3f pad; - TrainCarStuff* tempLocomotive; - TrainCarStuff* tempTender; - TrainCarStuff* tempPassengerCar; - Vec3s trainCarRot; - VehicleStuff* tempBoxTruck; - VehicleStuff* tempSchoolBus; - VehicleStuff* tempTankerTruck; - VehicleStuff* tempCar; - PaddleBoatStuff* tempPaddleWheelBoat; - Vec3s paddleWheelBoatRot; - s32 loopIndex; - s32 loopIndex2; - f32 origXPos; - f32 origZPos; + generate_train_waypoints(); - for (loopIndex = 0; loopIndex < NUM_TRAINS; loopIndex++) { - tempLocomotive = &gTrainList[loopIndex].locomotive; - origXPos = tempLocomotive->position[0]; - origZPos = tempLocomotive->position[2]; - trainCarYRot = update_vehicle_following_waypoint( - tempLocomotive->position, (s16*) &tempLocomotive->waypointIndex, gTrainList[loopIndex].speed); - tempLocomotive->velocity[0] = tempLocomotive->position[0] - origXPos; - tempLocomotive->velocity[2] = tempLocomotive->position[2] - origZPos; - vec3s_set(trainCarRot, 0, trainCarYRot, 0); - tempLocomotive->actorIndex = add_actor_to_empty_slot(tempLocomotive->position, trainCarRot, - tempLocomotive->velocity, ACTOR_TRAIN_ENGINE); + s32 numTrains = 2; + s32 centerWaypoint = 160; - tempTender = &gTrainList[loopIndex].tender; - if (tempTender->isActive == 1) { - origXPos = tempTender->position[0]; - origZPos = tempTender->position[2]; - trainCarYRot = update_vehicle_following_waypoint( - tempTender->position, (s16*) &tempTender->waypointIndex, gTrainList[loopIndex].speed); - tempTender->velocity[0] = tempTender->position[0] - origXPos; - tempTender->velocity[2] = tempTender->position[2] - origZPos; - vec3s_set(trainCarRot, 0, trainCarYRot, 0); - tempTender->actorIndex = add_actor_to_empty_slot(tempTender->position, trainCarRot, - tempTender->velocity, ACTOR_TRAIN_TENDER); - } - - for (loopIndex2 = 0; loopIndex2 < NUM_PASSENGER_CAR_ENTRIES; loopIndex2++) { - tempPassengerCar = &gTrainList[loopIndex].passengerCars[loopIndex2]; - if (tempPassengerCar->isActive == 1) { - origXPos = tempPassengerCar->position[0]; - origZPos = tempPassengerCar->position[2]; - trainCarYRot = update_vehicle_following_waypoint(tempPassengerCar->position, - (s16*) &tempPassengerCar->waypointIndex, - gTrainList[loopIndex].speed); - tempPassengerCar->velocity[0] = tempPassengerCar->position[0] - origXPos; - tempPassengerCar->velocity[2] = tempPassengerCar->position[2] - origZPos; - vec3s_set(trainCarRot, 0, trainCarYRot, 0); - tempPassengerCar->actorIndex = - add_actor_to_empty_slot(tempPassengerCar->position, trainCarRot, tempPassengerCar->velocity, - ACTOR_TRAIN_PASSENGER_CAR); - } - } + // Spawn two trains + for (size_t i = 0; i < numTrains; ++i) { + uint32_t waypoint = CalculateWaypointDistribution(i, numTrains, gVehicle2DWaypointLength, centerWaypoint); + + gWorldInstance.AddTrain(5, 5.0f, waypoint); } } -void KalimariDesert::UpdateVehicles() { - update_vehicle_trains(); -} - void KalimariDesert::BeginPlay() { } void KalimariDesert::Render(struct UnkStruct_800DC5EC* arg0) { func_802B5D64(D_800DC610, D_802B87D4, 0, 1); @@ -308,7 +256,7 @@ void KalimariDesert::RenderCredits() { void KalimariDesert::Collision() {} void KalimariDesert::GenerateCollision() { - parse_course_displaylists(d_course_kalimari_desert_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_kalimari_desert_addr)); func_80295C6C(); D_8015F8E4 = gCourseMinY - 10.0f; } diff --git a/src/engine/courses/KalimariDesert.h b/src/engine/courses/KalimariDesert.h index 09baf9265..345b807c1 100644 --- a/src/engine/courses/KalimariDesert.h +++ b/src/engine/courses/KalimariDesert.h @@ -29,8 +29,6 @@ public: virtual void Init() override; virtual void MinimapSettings() override; virtual void InitCourseObjects() override; - virtual void UpdateCourseObjects() override; - virtual void RenderCourseObjects(s32 cameraId) override; virtual void SomeSounds() override; virtual void WhatDoesThisDo(Player* player, int8_t playerId) override; virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override; @@ -40,7 +38,6 @@ public: virtual void Render(struct UnkStruct_800DC5EC*) override; virtual void RenderCredits() override; virtual void SpawnVehicles() override; - virtual void UpdateVehicles() override; virtual void Collision() override; virtual void SpawnBombKarts() override; virtual void GenerateCollision() override; diff --git a/src/engine/courses/KoopaTroopaBeach.cpp b/src/engine/courses/KoopaTroopaBeach.cpp index d22c8da35..8cf28a1d9 100644 --- a/src/engine/courses/KoopaTroopaBeach.cpp +++ b/src/engine/courses/KoopaTroopaBeach.cpp @@ -28,6 +28,7 @@ extern "C" { #include "staff_ghosts.h" #include "actors.h" #include "collision.h" + #include "code_8003DC40.h" #include "memory.h" extern const char *koopa_troopa_beach_dls[]; extern s8 gPlayerCount; @@ -38,6 +39,9 @@ KoopaTroopaBeach::KoopaTroopaBeach() { this->gfx = d_course_koopa_troopa_beach_packed_dls; this->gfxSize = 5720; this->textures = koopa_troopa_beach_textures; + Props.MinimapTexture = gTextureCourseOutlineKoopaTroopaBeach; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Id = "mk:koopa_beach"; Props.Name = "koopa troopa beach"; @@ -74,13 +78,13 @@ KoopaTroopaBeach::KoopaTroopaBeach() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_koopa_troopa_beach_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_koopa_troopa_beach_track_waypoints; - Props.PathTable2[1] = d_course_koopa_troopa_beach_track_waypoints_2; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_track_waypoints); + Props.PathTable2[1] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_track_waypoints_2); Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -104,8 +108,8 @@ void KoopaTroopaBeach::LoadTextures() { void KoopaTroopaBeach::SpawnActors() { init_actor_hot_air_balloon_item_box(328.0f * gCourseDirection, 70.0f, 2541.0f); - spawn_all_item_boxes(d_course_koopa_troopa_beach_item_box_spawns); - spawn_palm_trees(d_course_koopa_troopa_beach_tree_spawn); + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_item_box_spawns)); + spawn_palm_trees((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_tree_spawn)); } void KoopaTroopaBeach::Init() {} @@ -179,17 +183,13 @@ void KoopaTroopaBeach::WhatDoesThisDo(Player* player, int8_t playerId) {} void KoopaTroopaBeach::WhatDoesThisDoAI(Player* player, int8_t playerId) {} void KoopaTroopaBeach::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(140, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(165, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(330, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(550, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(595, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(140, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(165, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(330, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(550, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(595, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -235,8 +235,12 @@ void KoopaTroopaBeach::RenderCredits() { void KoopaTroopaBeach::Collision() {} +void KoopaTroopaBeach::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) { + func_8003E37C(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7); +} + void KoopaTroopaBeach::GenerateCollision() { - parse_course_displaylists(d_course_koopa_troopa_beach_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_addr)); func_80295C6C(); find_vtx_and_set_colours(segmented_gfx_to_virtual(reinterpret_cast(0x0700ADE0)), -0x6A, 255, 255, 255); find_vtx_and_set_colours(segmented_gfx_to_virtual(reinterpret_cast(0x0700A540)), -0x6A, 255, 255, 255); diff --git a/src/engine/courses/KoopaTroopaBeach.h b/src/engine/courses/KoopaTroopaBeach.h index df4c77f9f..9a1ed3612 100644 --- a/src/engine/courses/KoopaTroopaBeach.h +++ b/src/engine/courses/KoopaTroopaBeach.h @@ -40,6 +40,7 @@ public: virtual void Render(struct UnkStruct_800DC5EC*) override; virtual void RenderCredits() override; virtual void Collision() override; + virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override; virtual void SpawnBombKarts() override; virtual void GenerateCollision() override; virtual void Water() override; diff --git a/src/engine/courses/LuigiRaceway.cpp b/src/engine/courses/LuigiRaceway.cpp index 79e7cadb0..173f3ef56 100644 --- a/src/engine/courses/LuigiRaceway.cpp +++ b/src/engine/courses/LuigiRaceway.cpp @@ -28,6 +28,7 @@ extern "C" { #include "staff_ghosts.h" #include "actors.h" #include "collision.h" + #include "code_8003DC40.h" #include "memory.h" extern const char *luigi_raceway_dls[]; extern s16 currentScreenSection; @@ -38,6 +39,9 @@ LuigiRaceway::LuigiRaceway() { this->gfx = d_course_luigi_raceway_packed_dls; this->gfxSize = 6377; this->textures = luigi_raceway_textures; + Props.MinimapTexture = gTextureCourseOutlineLuigiRaceway; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 96; Props.Id = "mk:luigi_raceway"; Props.Name = "luigi raceway"; @@ -74,12 +78,12 @@ LuigiRaceway::LuigiRaceway() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_luigi_raceway_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_luigi_raceway_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_luigi_raceway_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_luigi_raceway_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -105,8 +109,8 @@ void LuigiRaceway::LoadTextures() { } void LuigiRaceway::SpawnActors() { - spawn_foliage(d_course_luigi_raceway_tree_spawn); - spawn_all_item_boxes(d_course_luigi_raceway_item_box_spawns); + spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_luigi_raceway_tree_spawn)); + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_luigi_raceway_item_box_spawns)); } void LuigiRaceway::Init() {} @@ -186,17 +190,13 @@ void LuigiRaceway::WhatDoesThisDoAI(Player* player, int8_t playerId) { } void LuigiRaceway::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -328,8 +328,12 @@ void LuigiRaceway::RenderCredits() { void LuigiRaceway::Collision() {} +void LuigiRaceway::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) { + func_8003E9EC(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7); +} + void LuigiRaceway::GenerateCollision() { - parse_course_displaylists(d_course_luigi_raceway_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_luigi_raceway_addr)); func_80295C6C(); D_8015F8E4 = gCourseMinY - 10.0f; } diff --git a/src/engine/courses/LuigiRaceway.h b/src/engine/courses/LuigiRaceway.h index 7bab671b7..ef4cb5783 100644 --- a/src/engine/courses/LuigiRaceway.h +++ b/src/engine/courses/LuigiRaceway.h @@ -38,8 +38,9 @@ public: virtual void SetStaffGhost() override; virtual void BeginPlay() override; virtual void Render(struct UnkStruct_800DC5EC*) override; - virtual void RenderCredits() override; + virtual void RenderCredits() override; virtual void Collision() override; + virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override; virtual void SpawnBombKarts() override; virtual void GenerateCollision() override; virtual void Destroy() override; diff --git a/src/engine/courses/MarioRaceway.cpp b/src/engine/courses/MarioRaceway.cpp index 575c6300b..3aff3c6c1 100644 --- a/src/engine/courses/MarioRaceway.cpp +++ b/src/engine/courses/MarioRaceway.cpp @@ -37,6 +37,9 @@ MarioRaceway::MarioRaceway() { this->gfx = d_course_mario_raceway_packed_dls; this->gfxSize = 3367; this->textures = mario_raceway_textures; + Props.MinimapTexture = gTextureCourseOutlineMarioRaceway; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Id = "mk:mario_raceway"; Props.Name = "Mario Raceway"; @@ -74,12 +77,12 @@ MarioRaceway::MarioRaceway() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_mario_raceway_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_mario_raceway_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_mario_raceway_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_mario_raceway_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -117,9 +120,9 @@ void MarioRaceway::SpawnActors() { Vec3f position; Vec3f velocity = { 0.0f, 0.0f, 0.0f }; Vec3s rotation = { 0, 0, 0 }; - spawn_foliage(d_course_mario_raceway_tree_spawns); - spawn_piranha_plants(d_course_mario_raceway_piranha_plant_spawns); - spawn_all_item_boxes(d_course_mario_raceway_item_box_spawns); + spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_mario_raceway_tree_spawns)); + spawn_piranha_plants((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_mario_raceway_piranha_plant_spawns)); + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_mario_raceway_item_box_spawns)); vec3f_set(position, 150.0f, 40.0f, -1300.0f); position[0] *= gCourseDirection; add_actor_to_empty_slot(position, rotation, velocity, ACTOR_MARIO_SIGN); @@ -192,17 +195,13 @@ void MarioRaceway::WhatDoesThisDoAI(Player* player, int8_t playerId) { } void MarioRaceway::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -346,7 +345,7 @@ void MarioRaceway::GenerateCollision() { generate_collision_mesh_with_defaults(segmented_gfx_to_virtual(reinterpret_cast(0x07002D68))); } - parse_course_displaylists(d_course_mario_raceway_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_mario_raceway_addr)); func_80295C6C(); D_8015F8E4 = gCourseMinY - 10.0f; } diff --git a/src/engine/courses/MooMooFarm.cpp b/src/engine/courses/MooMooFarm.cpp index 75d7c0dc5..f0d9b3978 100644 --- a/src/engine/courses/MooMooFarm.cpp +++ b/src/engine/courses/MooMooFarm.cpp @@ -40,6 +40,9 @@ MooMooFarm::MooMooFarm() { this->gfx = d_course_moo_moo_farm_packed_dls; this->gfxSize = 3304; this->textures = moo_moo_farm_textures; + Props.MinimapTexture = gTextureCourseOutlineMooMooFarm; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Name = "moo moo farm"; Props.DebugName = "farm"; @@ -75,12 +78,12 @@ MooMooFarm::MooMooFarm() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_moo_moo_farm_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_moo_moo_farm_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_moo_moo_farm_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_moo_moo_farm_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -117,9 +120,9 @@ void MooMooFarm::LoadTextures() { void MooMooFarm::SpawnActors() { if (gPlayerCountSelection1 != 4) { - spawn_foliage(d_course_moo_moo_farm_tree_spawn); + spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_moo_moo_farm_tree_spawn)); } - spawn_all_item_boxes(d_course_moo_moo_farm_item_box_spawns); + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_moo_moo_farm_item_box_spawns)); } void MooMooFarm::Init() {} @@ -237,17 +240,13 @@ void MooMooFarm::WhatDoesThisDoAI(Player* player, int8_t playerId) { } void MooMooFarm::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -340,7 +339,7 @@ void MooMooFarm::RenderCredits() { void MooMooFarm::Collision() {} void MooMooFarm::GenerateCollision() { - parse_course_displaylists(d_course_moo_moo_farm_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_moo_moo_farm_addr)); func_80295C6C(); D_8015F8E4 = gCourseMinY - 10.0f; } diff --git a/src/engine/courses/PodiumCeremony.cpp b/src/engine/courses/PodiumCeremony.cpp index ab641524a..a0c66bd09 100644 --- a/src/engine/courses/PodiumCeremony.cpp +++ b/src/engine/courses/PodiumCeremony.cpp @@ -37,6 +37,8 @@ PodiumCeremony::PodiumCeremony() { this->gfx = d_course_royal_raceway_packed_dls; this->gfxSize = 5670; this->textures = royal_raceway_textures; + Props.D_800E5548[0] = 0; + Props.D_800E5548[1] = 0; Props.Name = "royal raceway"; Props.DebugName = "p circuit"; @@ -69,12 +71,12 @@ PodiumCeremony::PodiumCeremony() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_royal_raceway_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_royal_raceway_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_royal_raceway_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_royal_raceway_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -98,9 +100,9 @@ void PodiumCeremony::LoadTextures() { } void PodiumCeremony::SpawnActors() { - spawn_foliage(d_course_royal_raceway_tree_spawn); - spawn_all_item_boxes(d_course_royal_raceway_item_box_spawns); - spawn_piranha_plants(d_course_royal_raceway_piranha_plant_spawn); + spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_royal_raceway_tree_spawn)); + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_royal_raceway_item_box_spawns)); + spawn_piranha_plants((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_royal_raceway_piranha_plant_spawn)); } void PodiumCeremony::Init() { } @@ -164,17 +166,13 @@ void PodiumCeremony::WhatDoesThisDoAI(Player* player, int8_t playerId) { } void PodiumCeremony::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -233,7 +231,7 @@ void PodiumCeremony::RenderCredits() { void PodiumCeremony::Collision() {} void PodiumCeremony::GenerateCollision() { - parse_course_displaylists(d_course_royal_raceway_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_royal_raceway_addr)); func_80295C6C(); D_8015F8E4 = -60.0f; } diff --git a/src/engine/courses/RainbowRoad.cpp b/src/engine/courses/RainbowRoad.cpp index 949ac705d..1cde1cf94 100644 --- a/src/engine/courses/RainbowRoad.cpp +++ b/src/engine/courses/RainbowRoad.cpp @@ -37,6 +37,9 @@ RainbowRoad::RainbowRoad() { this->gfx = d_course_rainbow_road_packed_dls; this->gfxSize = 5670; this->textures = rainbow_road_textures; + Props.MinimapTexture = gTextureCourseOutlineRainbowRoad; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 96; Props.Name = "rainbow road"; Props.DebugName = "rainbow"; @@ -72,12 +75,12 @@ RainbowRoad::RainbowRoad() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_rainbow_road_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_rainbow_road_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_rainbow_road_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_rainbow_road_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -101,7 +104,7 @@ void RainbowRoad::LoadTextures() { } void RainbowRoad::SpawnActors() { - spawn_all_item_boxes(d_course_rainbow_road_item_box_spawns); + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_rainbow_road_item_box_spawns)); } void RainbowRoad::Init() {} @@ -157,17 +160,13 @@ void RainbowRoad::WhatDoesThisDo(Player* player, int8_t playerId) {} void RainbowRoad::WhatDoesThisDoAI(Player* player, int8_t playerId) {} void RainbowRoad::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -195,7 +194,7 @@ void RainbowRoad::Collision() {} void RainbowRoad::GenerateCollision() { D_800DC5C8 = 1; - parse_course_displaylists(d_course_rainbow_road_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_rainbow_road_addr)); func_80295C6C(); D_8015F8E4 = 0.0f; // d_course_rainbow_road_packed_dl_2068 diff --git a/src/engine/courses/RoyalRaceway.cpp b/src/engine/courses/RoyalRaceway.cpp index ee6d645cb..355012e2e 100644 --- a/src/engine/courses/RoyalRaceway.cpp +++ b/src/engine/courses/RoyalRaceway.cpp @@ -37,6 +37,9 @@ RoyalRaceway::RoyalRaceway() { this->gfx = d_course_royal_raceway_packed_dls; this->gfxSize = 5670; this->textures = royal_raceway_textures; + Props.MinimapTexture = gTextureCourseOutlineRoyalRaceway; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Name = "royal raceway"; Props.DebugName = "p circuit"; @@ -72,12 +75,12 @@ RoyalRaceway::RoyalRaceway() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_royal_raceway_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_royal_raceway_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_royal_raceway_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_royal_raceway_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -112,9 +115,9 @@ void RoyalRaceway::LoadTextures() { } void RoyalRaceway::SpawnActors() { - spawn_foliage(d_course_royal_raceway_tree_spawn); - spawn_all_item_boxes(d_course_royal_raceway_item_box_spawns); - spawn_piranha_plants(d_course_royal_raceway_piranha_plant_spawn); + spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_royal_raceway_tree_spawn)); + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_royal_raceway_item_box_spawns)); + spawn_piranha_plants((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_royal_raceway_piranha_plant_spawn)); } void RoyalRaceway::Init() {} @@ -178,17 +181,13 @@ void RoyalRaceway::WhatDoesThisDoAI(Player* player, int8_t playerId) { } void RoyalRaceway::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -247,7 +246,7 @@ void RoyalRaceway::RenderCredits() { void RoyalRaceway::Collision() {} void RoyalRaceway::GenerateCollision() { - parse_course_displaylists(d_course_royal_raceway_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_royal_raceway_addr)); func_80295C6C(); D_8015F8E4 = -60.0f; } diff --git a/src/engine/courses/SherbetLand.cpp b/src/engine/courses/SherbetLand.cpp index 947f74b69..0aee5147a 100644 --- a/src/engine/courses/SherbetLand.cpp +++ b/src/engine/courses/SherbetLand.cpp @@ -37,6 +37,9 @@ SherbetLand::SherbetLand() { this->gfx = d_course_sherbet_land_packed_dls; this->gfxSize = 1803; this->textures = sherbet_land_textures; + Props.MinimapTexture = gTextureCourseOutlineSherbetLand; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Name = "sherbet land"; Props.DebugName = "sherbet"; @@ -72,12 +75,12 @@ SherbetLand::SherbetLand() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_sherbet_land_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_sherbet_land_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_sherbet_land_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_sherbet_land_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -101,7 +104,7 @@ void SherbetLand::LoadTextures() { } void SherbetLand::SpawnActors() { - spawn_all_item_boxes(d_course_sherbet_land_item_box_spawns); + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_sherbet_land_item_box_spawns)); } void SherbetLand::Init() {} @@ -146,17 +149,13 @@ void SherbetLand::WhatDoesThisDo(Player* player, int8_t playerId) {} void SherbetLand::WhatDoesThisDoAI(Player* player, int8_t playerId) {} void SherbetLand::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -184,7 +183,7 @@ void SherbetLand::RenderCredits() { void SherbetLand::Collision() {} void SherbetLand::GenerateCollision() { - parse_course_displaylists(d_course_sherbet_land_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_sherbet_land_addr)); func_80295C6C(); D_8015F8E4 = -18.0f; // d_course_sherbet_land_packed_dl_1EB8 diff --git a/src/engine/courses/Skyscraper.cpp b/src/engine/courses/Skyscraper.cpp index 1a565fbbf..ac6dde347 100644 --- a/src/engine/courses/Skyscraper.cpp +++ b/src/engine/courses/Skyscraper.cpp @@ -38,6 +38,9 @@ Skyscraper::Skyscraper() { this->gfx = d_course_skyscraper_packed_dls; this->gfxSize = 548; this->textures = skyscraper_textures; + Props.MinimapTexture = gTextureCourseOutlineSkyscraper; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Name = "skyscraper"; Props.DebugName = "skyscraper"; diff --git a/src/engine/courses/TestCourse.cpp b/src/engine/courses/TestCourse.cpp index f999457fd..7ce8f9cca 100644 --- a/src/engine/courses/TestCourse.cpp +++ b/src/engine/courses/TestCourse.cpp @@ -44,6 +44,7 @@ extern "C" { TestCourse::TestCourse() { this->gfxSize = 100; this->textures = NULL; + Props.MinimapTexture = gTextureCourseOutlineMarioRaceway; Props.Id = "mk:test_course"; Props.Name = "Test Course"; @@ -59,7 +60,7 @@ TestCourse::TestCourse() { Props.NearPersp = 9.0f; Props.FarPersp = 4500.0f; - Props.PathSizes = {52, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}; + Props.PathSizes = {51, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}; Props.D_0D009418[0] = 4.1666665f; Props.D_0D009418[1] = 5.5833334f; @@ -81,12 +82,12 @@ TestCourse::TestCourse() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - //Props.PathTable[0] = test_course_path; + Props.PathTable[0] = test_course_path; Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - //Props.PathTable2[0] = test_course_path; + Props.PathTable2[0] = test_course_path; Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -126,6 +127,9 @@ void TestCourse::LoadTextures() { void TestCourse::SpawnActors() { struct ActorSpawnData itemboxes[] = { + { 200, 1500, 200 , 0}, + { 350, 2500, 300 , 1}, + { 400, 2000, 350 , 2}, { 40, 0, -800, 0}, { -40, 0, -800, 0}, { 0, 0, -800, 0}, @@ -138,13 +142,27 @@ struct ActorSpawnData itemboxes[] = { }; struct ActorSpawnData rocks[] = { - {{ 200, 3000, 200 }, {0}}, + {{ 200, 1500, 200 }, {0}}, {{ 350, 2500, 300 }, {1}}, {{ 400, 2000, 350 }, {2}}, {{ -32768, 0, 0 }, {0}}, }; - spawn_all_item_boxes((const char*)itemboxes); - spawn_falling_rocks((const char*)rocks); + spawn_all_item_boxes(itemboxes); + spawn_falling_rocks(rocks); + + struct RailroadCrossing* rrxing; + Vec3f position; + Vec3f velocity = { 0.0f, 0.0f, 0.0f }; + Vec3s rotation = { 0, 0, 0 }; + vec3f_set(position, 50.0f, 2.0f, 50.0f); + + Vec3f crossingPos = {0, 2, 0}; + uintptr_t* crossing1 = (uintptr_t*) gWorldInstance.AddCrossing(crossingPos, 0, 2, 900.0f, 650.0f); + + position[0] *= gCourseDirection; + rrxing = (struct RailroadCrossing*) &gActorList[add_actor_to_empty_slot(position, rotation, velocity, + ACTOR_RAILROAD_CROSSING)]; + rrxing->crossingTrigger = crossing1; } void TestCourse::Init() {} @@ -162,6 +180,77 @@ void TestCourse::MinimapSettings() { D_80165728 = -240; } +Path2D test_course_path2D[] = { + { 0, 0}, + { 0, -100}, + { 0, -200}, + { 0, -300}, + { 0, -400}, + { 0, -500}, + { 0, -600}, + { 0, -700}, + { 0, -800}, + { 0, -900}, + { 0, -1000}, + { 0, -1096}, // Main point 1 + { 100, -1090}, + { 200, -1085}, + { 300, -1080}, + { 400, -1075}, + { 500, -1072}, // Curve begins to smooth here + { 600, -1068}, + { 700, -1065}, + { 800, -1063}, + { 900, -1061}, + { 984, -1060}, // Main point 2 + { 990, -900}, + { 995, -800}, + { 997, -700}, + { 998, -600}, + { 999, -500}, + { 999, -400}, + { 999, -300}, + { 999, -200}, + { 999, -100}, + { 999, 0}, + { 999, 100}, + { 999, 200}, + { 999, 300}, + { 999, 400}, + { 999, 500}, + { 999, 600}, + { 999, 700}, + { 999, 800}, + { 999, 900}, + { 999, 940}, // Main point 3 + { 900, 945}, + { 800, 945}, + { 700, 947}, + { 600, 948}, + { 500, 949}, + { 400, 949}, + { 300, 949}, + { 200, 950}, + { 100, 950}, + { 0, 950}, // Main point 4 + + // End of path + { -32768, -32768 } // Terminator +}; + +void TestCourse::SpawnVehicles() { + gVehicle2DWaypoint = test_course_path2D; + gVehicle2DWaypointLength = 53; + D_80162EB0 = spawn_actor_on_surface(test_course_path2D[0].x, 2000.0f, test_course_path2D[0].z); + + gWorldInstance.AddTrain(5, 5.0f, 0); + gWorldInstance.AddTrain(5, 5.0f, 8); +} + +void TestCourse::UpdateVehicles() { + update_vehicle_trains(); +} + void TestCourse::InitCourseObjects() {} void TestCourse::SomeSounds() {} @@ -197,17 +286,13 @@ void TestCourse::WhatDoesThisDoAI(Player* player, int8_t playerId) { } void TestCourse::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -242,7 +327,7 @@ void TestCourse::Collision() {} void TestCourse::GenerateCollision() { generate_collision_mesh_with_defaults(mario_Plane_001_mesh); - parse_course_displaylists((const char*)test_course_addr); + parse_course_displaylists((TrackSectionsI*)test_course_addr); func_80295C6C(); D_8015F8E4 = gCourseMinY - 10.0f; } diff --git a/src/engine/courses/TestCourse.h b/src/engine/courses/TestCourse.h index 91b279d2e..313b1ac58 100644 --- a/src/engine/courses/TestCourse.h +++ b/src/engine/courses/TestCourse.h @@ -39,6 +39,8 @@ public: virtual void Render(struct UnkStruct_800DC5EC*) override; virtual void RenderCredits() override; virtual void Collision() override; + virtual void SpawnVehicles() override; + virtual void UpdateVehicles() override; virtual void SpawnBombKarts() override; virtual void GenerateCollision() override; virtual void Destroy() override; diff --git a/src/engine/courses/ToadsTurnpike.cpp b/src/engine/courses/ToadsTurnpike.cpp index 77d8dff33..cb6420cba 100644 --- a/src/engine/courses/ToadsTurnpike.cpp +++ b/src/engine/courses/ToadsTurnpike.cpp @@ -9,6 +9,8 @@ #include "BombKart.h" #include "assets/toads_turnpike_data.h" +#include "engine/vehicles/Utils.h" + extern "C" { #include "main.h" #include "camera.h" @@ -40,6 +42,9 @@ ToadsTurnpike::ToadsTurnpike() { this->gfx = d_course_toads_turnpike_packed_dls; this->gfxSize = 3427; this->textures = toads_turnpike_textures; + Props.MinimapTexture = gTextureCourseOutlineToadsTurnpike; + Props.D_800E5548[0] = 128; + Props.D_800E5548[1] = 64; Props.Name = "toad's turnpike"; Props.DebugName = "highway"; @@ -53,7 +58,7 @@ ToadsTurnpike::ToadsTurnpike() { Props.NearPersp = 9.0f; Props.FarPersp = 4500.0f; - Props.PathSizes = {0x3E8, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}; + Props.PathSizes = {1000, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}; Props.D_0D009418[0] = 4.1666665f; Props.D_0D009418[1] = 5.5833334f; @@ -75,12 +80,12 @@ ToadsTurnpike::ToadsTurnpike() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_toads_turnpike_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_toads_turnpike_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_toads_turnpike_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_toads_turnpike_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -104,14 +109,7 @@ void ToadsTurnpike::LoadTextures() { } void ToadsTurnpike::SpawnActors() { - D_801625EC = 43; - D_801625F4 = 13; - D_801625F0 = 4; - D_802B87B0 = 993; - D_802B87B4 = 1000; - parse_course_displaylists(d_course_toads_turnpike_addr); - func_80295C6C(); - D_8015F8E4 = gCourseMinY - 10.0f; + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_toads_turnpike_item_box_spawns)); } void ToadsTurnpike::Init() {} @@ -162,17 +160,13 @@ void ToadsTurnpike::WhatDoesThisDoAI(Player* player, int8_t playerId) { } void ToadsTurnpike::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -218,55 +212,51 @@ void ToadsTurnpike::RenderCredits() { void ToadsTurnpike::Collision() {} void ToadsTurnpike::SpawnVehicles() { - s16 trainCarYRot; - UNUSED Vec3f pad; - TrainCarStuff* tempLocomotive; - TrainCarStuff* tempTender; - TrainCarStuff* tempPassengerCar; - Vec3s trainCarRot; - VehicleStuff* tempBoxTruck; - VehicleStuff* tempSchoolBus; - VehicleStuff* tempTankerTruck; - VehicleStuff* tempCar; - PaddleBoatStuff* tempPaddleWheelBoat; - Vec3s paddleWheelBoatRot; - s32 loopIndex; - s32 loopIndex2; - f32 origXPos; - f32 origZPos; + f32 a = ((gCCSelection * 90.0) / 216.0f) + 4.583333333333333; + f32 b = ((gCCSelection * 90.0) / 216.0f) + 2.9166666666666665; + uint32_t waypoint; - for (loopIndex = 0; loopIndex < NUM_RACE_BOX_TRUCKS; loopIndex++) { - tempBoxTruck = &gBoxTruckList[loopIndex]; - spawn_vehicle_on_road(tempBoxTruck); - tempBoxTruck->actorIndex = add_actor_to_empty_slot(tempBoxTruck->position, tempBoxTruck->rotation, - tempBoxTruck->velocity, ACTOR_BOX_TRUCK); - } - for (loopIndex = 0; loopIndex < NUM_RACE_SCHOOL_BUSES; loopIndex++) { - tempSchoolBus = &gSchoolBusList[loopIndex]; - spawn_vehicle_on_road(tempSchoolBus); - tempSchoolBus->actorIndex = add_actor_to_empty_slot(tempSchoolBus->position, tempSchoolBus->rotation, - tempSchoolBus->velocity, ACTOR_SCHOOL_BUS); - } - for (loopIndex = 0; loopIndex < NUM_RACE_TANKER_TRUCKS; loopIndex++) { - tempTankerTruck = &gTankerTruckList[loopIndex]; - spawn_vehicle_on_road(tempTankerTruck); - tempTankerTruck->actorIndex = - add_actor_to_empty_slot(tempTankerTruck->position, tempTankerTruck->rotation, - tempTankerTruck->velocity, ACTOR_TANKER_TRUCK); - } - for (loopIndex = 0; loopIndex < NUM_RACE_CARS; loopIndex++) { - tempCar = &gCarList[loopIndex]; - spawn_vehicle_on_road(tempCar); - tempCar->actorIndex = - add_actor_to_empty_slot(tempCar->position, tempCar->rotation, tempCar->velocity, ACTOR_CAR); - } -} + if (gModeSelection == TIME_TRIALS) { + for (size_t i = 0; i < NUM_TIME_TRIAL_BOX_TRUCKS; i++) { + waypoint = CalculateWaypointDistribution(i, NUM_TIME_TRIAL_BOX_TRUCKS, gWaypointCountByPathIndex[0], 0); + gWorldInstance.AddTruck(a, b, &D_80164550[0][0], waypoint); + } -void ToadsTurnpike::UpdateVehicles() { - update_vehicle_box_trucks(); - update_vehicle_school_bus(); - update_vehicle_tanker_trucks(); - update_vehicle_cars(); + for (size_t i = 0; i < NUM_TIME_TRIAL_SCHOOL_BUSES; i++) { + waypoint = CalculateWaypointDistribution(i, NUM_TIME_TRIAL_SCHOOL_BUSES, gWaypointCountByPathIndex[0], 75); + gWorldInstance.AddBus(a, b, &D_80164550[0][0], waypoint); + } + + for (size_t i = 0; i < NUM_TIME_TRIAL_TANKER_TRUCKS; i++) { + waypoint = CalculateWaypointDistribution(i, NUM_TIME_TRIAL_TANKER_TRUCKS, gWaypointCountByPathIndex[0], 50); + gWorldInstance.AddTankerTruck(a, b, &D_80164550[0][0], waypoint); + } + + for (size_t i = 0; i < NUM_TIME_TRIAL_CARS; i++) { + waypoint = CalculateWaypointDistribution(i, NUM_TIME_TRIAL_CARS, gWaypointCountByPathIndex[0], 25); + gWorldInstance.AddCar(a, b, &D_80164550[0][0], waypoint); + } + } else { // All other modes + for (size_t i = 0; i < NUM_RACE_BOX_TRUCKS; i++) { + uint32_t waypoint = CalculateWaypointDistribution(i, NUM_RACE_BOX_TRUCKS, gWaypointCountByPathIndex[0], 0); + gWorldInstance.AddTruck(a, b, &D_80164550[0][0], waypoint); + } + + for (size_t i = 0; i < NUM_RACE_SCHOOL_BUSES; i++) { + waypoint = CalculateWaypointDistribution(i, NUM_RACE_SCHOOL_BUSES, gWaypointCountByPathIndex[0], 75); + gWorldInstance.AddBus(a, b,&D_80164550[0][0], waypoint); + } + + for (size_t i = 0; i < NUM_RACE_TANKER_TRUCKS; i++) { + waypoint = CalculateWaypointDistribution(i, NUM_RACE_TANKER_TRUCKS, gWaypointCountByPathIndex[0], 50); + gWorldInstance.AddTankerTruck(a, b, &D_80164550[0][0], waypoint); + } + + for (size_t i = 0; i < NUM_RACE_CARS; i++) { + waypoint = CalculateWaypointDistribution(i, NUM_RACE_CARS, gWaypointCountByPathIndex[0], 25); + gWorldInstance.AddCar(a, b, &D_80164550[0][0], waypoint); + } + } } void ToadsTurnpike::GenerateCollision() { @@ -275,7 +265,7 @@ void ToadsTurnpike::GenerateCollision() { D_801625F0 = 4; D_802B87B0 = 993; D_802B87B4 = 1000; - parse_course_displaylists(d_course_toads_turnpike_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_toads_turnpike_addr)); func_80295C6C(); D_8015F8E4 = gCourseMinY - 10.0f; } diff --git a/src/engine/courses/ToadsTurnpike.h b/src/engine/courses/ToadsTurnpike.h index 9e25a288f..fc6078721 100644 --- a/src/engine/courses/ToadsTurnpike.h +++ b/src/engine/courses/ToadsTurnpike.h @@ -40,7 +40,6 @@ public: virtual void RenderCredits() override; virtual void Collision() override; virtual void SpawnVehicles() override; - virtual void UpdateVehicles() override; virtual void SpawnBombKarts() override; virtual void GenerateCollision() override; virtual void Destroy() override; diff --git a/src/engine/courses/WarioStadium.cpp b/src/engine/courses/WarioStadium.cpp index 5dc500d29..6778c1033 100644 --- a/src/engine/courses/WarioStadium.cpp +++ b/src/engine/courses/WarioStadium.cpp @@ -28,6 +28,7 @@ extern "C" { #include "staff_ghosts.h" #include "actors.h" #include "collision.h" + #include "code_8003DC40.h" #include "memory.h" extern const char *wario_stadium_dls[]; extern s16 currentScreenSection; @@ -38,6 +39,9 @@ WarioStadium::WarioStadium() { this->gfx = d_course_wario_stadium_packed_dls; this->gfxSize = 5272; this->textures = wario_stadium_textures; + Props.MinimapTexture = gTextureCourseOutlineWarioStadium; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Name = "wario stadium"; Props.DebugName = "stadium"; @@ -73,12 +77,12 @@ WarioStadium::WarioStadium() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_wario_stadium_unknown_waypoints; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_wario_stadium_unknown_waypoints); Props.PathTable[1] = NULL; Props.PathTable[2] = NULL; Props.PathTable[3] = NULL; - Props.PathTable2[0] = d_course_wario_stadium_track_waypoints; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_wario_stadium_track_waypoints); Props.PathTable2[1] = NULL; Props.PathTable2[2] = NULL; Props.PathTable2[3] = NULL; @@ -106,7 +110,7 @@ void WarioStadium::SpawnActors() { Vec3f velocity = { 0.0f, 0.0f, 0.0f }; Vec3s rotation = { 0, 0, 0 }; - spawn_all_item_boxes(d_course_wario_stadium_item_box_spawns); + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_wario_stadium_item_box_spawns)); vec3f_set(position, -131.0f, 83.0f, 286.0f); position[0] *= gCourseDirection; add_actor_to_empty_slot(position, rotation, velocity, ACTOR_WARIO_SIGN); @@ -153,17 +157,13 @@ void WarioStadium::WhatDoesThisDo(Player* player, int8_t playerId) {} void WarioStadium::WhatDoesThisDoAI(Player* player, int8_t playerId) {} void WarioStadium::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(40, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(100, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(265, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(285, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(420, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -269,8 +269,12 @@ void WarioStadium::RenderCredits() { void WarioStadium::Collision() {} +void WarioStadium::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) { + func_8003EE2C(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7); +} + void WarioStadium::GenerateCollision() { - parse_course_displaylists(d_course_wario_stadium_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_wario_stadium_addr)); func_80295C6C(); D_8015F8E4 = gCourseMinY - 10.0f; // d_course_wario_stadium_packed_dl_C50 diff --git a/src/engine/courses/WarioStadium.h b/src/engine/courses/WarioStadium.h index 388e39c7f..c2f56564c 100644 --- a/src/engine/courses/WarioStadium.h +++ b/src/engine/courses/WarioStadium.h @@ -40,6 +40,7 @@ public: virtual void Render(struct UnkStruct_800DC5EC*) override; virtual void RenderCredits() override; virtual void Collision() override; + virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override; virtual void SpawnBombKarts() override; virtual void GenerateCollision() override; virtual void Destroy() override; diff --git a/src/engine/courses/YoshiValley.cpp b/src/engine/courses/YoshiValley.cpp index d7c142743..07af8bd1a 100644 --- a/src/engine/courses/YoshiValley.cpp +++ b/src/engine/courses/YoshiValley.cpp @@ -38,6 +38,9 @@ YoshiValley::YoshiValley() { this->gfx = d_course_yoshi_valley_packed_dls; this->gfxSize = 4140; this->textures = yoshi_valley_textures; + Props.MinimapTexture = gTextureCourseOutlineYoshiValley; + Props.D_800E5548[0] = 64; + Props.D_800E5548[1] = 64; Props.Name = "yoshi valley"; Props.DebugName = "maze"; @@ -73,15 +76,15 @@ YoshiValley::YoshiValley() { Props.D_0D009808[2] = 5.75f; Props.D_0D009808[3] = 6.3333334f; - Props.PathTable[0] = d_course_yoshi_valley_unknown_waypoints; - Props.PathTable[1] = d_course_yoshi_valley_unknown_waypoints_2; - Props.PathTable[2] = d_course_yoshi_valley_unknown_waypoints_3; - Props.PathTable[3] = d_course_yoshi_valley_unknown_waypoints_4; + Props.PathTable[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_yoshi_valley_unknown_waypoints); + Props.PathTable[1] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_yoshi_valley_unknown_waypoints_2); + Props.PathTable[2] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_yoshi_valley_unknown_waypoints_3); + Props.PathTable[3] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_yoshi_valley_unknown_waypoints_4); - Props.PathTable2[0] = d_course_yoshi_valley_track_waypoints; - Props.PathTable2[1] = d_course_yoshi_valley_track_waypoints_2; - Props.PathTable2[2] = d_course_yoshi_valley_track_waypoints_3; - Props.PathTable2[3] = d_course_yoshi_valley_track_waypoints_4; + Props.PathTable2[0] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_yoshi_valley_track_waypoints); + Props.PathTable2[1] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_yoshi_valley_track_waypoints_2); + Props.PathTable2[2] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_yoshi_valley_track_waypoints_3); + Props.PathTable2[3] = (TrackWaypoint*)LOAD_ASSET_RAW(d_course_yoshi_valley_track_waypoints_4); Props.Clouds = gYoshiValleyMooMooFarmClouds; Props.CloudList = gYoshiValleyMooMooFarmClouds; @@ -107,8 +110,8 @@ void YoshiValley::SpawnActors() { Vec3f velocity = { 0.0f, 0.0f, 0.0f }; Vec3s rotation = { 0, 0, 0 }; - spawn_foliage(d_course_yoshi_valley_tree_spawn); - spawn_all_item_boxes(d_course_yoshi_valley_item_box_spawns); + spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_yoshi_valley_tree_spawn)); + spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_yoshi_valley_item_box_spawns)); vec3f_set(position, -2300.0f, 0.0f, 634.0f); position[0] *= gCourseDirection; add_actor_to_empty_slot(position, rotation, velocity, ACTOR_YOSHI_EGG); @@ -168,17 +171,13 @@ void YoshiValley::WhatDoesThisDo(Player* player, int8_t playerId) {} void YoshiValley::WhatDoesThisDoAI(Player* player, int8_t playerId) {} void YoshiValley::SpawnBombKarts() { - World* world = GetWorld(); - - if (world) { - world->SpawnObject(std::make_unique(140, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(165, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(330, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(550, 1, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(595, 3, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - world->SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); - } + gWorldInstance.SpawnObject(std::make_unique(140, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(165, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(330, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(550, 1, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(595, 3, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); + gWorldInstance.SpawnObject(std::make_unique(0, 0, 0.8333333, 0, 0, 0, 0)); } // Positions the finishline on the minimap @@ -210,7 +209,7 @@ void YoshiValley::Collision() {} void YoshiValley::GenerateCollision() { Lights1 lights4 = gdSPDefLights1(100, 100, 100, 255, 254, 254, 0, 0, 120); func_802B5D64(&lights4, -0x38F0, 0x1C70, 1); - parse_course_displaylists(d_course_yoshi_valley_addr); + parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_yoshi_valley_addr)); func_80295C6C(); D_8015F8E4 = gCourseMinY - 10.0f; } diff --git a/src/engine/vehicles/Boat.cpp b/src/engine/vehicles/Boat.cpp new file mode 100644 index 000000000..bb2cda81d --- /dev/null +++ b/src/engine/vehicles/Boat.cpp @@ -0,0 +1,198 @@ +#include +#include "Boat.h" +#include + +extern "C" { +#include "macros.h" +#include "main.h" +#include "defines.h" +#include "code_80005FD0.h" +#include "actors.h" +#include "math_util.h" +#include "sounds.h" +#include "update_objects.h" +extern s8 gPlayerCount; +} + +ABoat::ABoat(size_t idx, f32 speed, u32 waypoint) { + Path2D* temp_a2; + u16 waypointOffset; + Index = idx; + Speed = speed; + + // Set to the default value + std::fill(SmokeParticles, SmokeParticles + 128, NULL_OBJECT_ID); + + waypointOffset = waypoint; + temp_a2 = &gVehicle2DWaypoint[waypointOffset]; + Position[0] = temp_a2->x; + Position[1] = D_80162EB2; + Position[2] = temp_a2->z; + WaypointIndex = Index * 0xB4; + ActorIndex = -1; + + if (gPlayerCount >= 3) { + IsActive = 0; + } else { + IsActive = 1; + } + Velocity[0] = 0.0f; + Velocity[1] = 0.0f; + Velocity[2] = 0.0f; +} + +void ABoat::Spawn() { + Vec3s paddleWheelBoatRot; + if (IsActive == 1) { + f32 origXPos = Position[0]; + f32 origZPos = Position[2]; + RotY = update_vehicle_following_waypoint( + Position, (s16*) &WaypointIndex, + Speed); + Velocity[0] = Position[0] - origXPos; + Velocity[2] = Position[2] - origZPos; + vec3s_set(paddleWheelBoatRot, 0, RotY, 0); + ActorIndex = add_actor_to_empty_slot(Position, paddleWheelBoatRot, + Velocity, ACTOR_PADDLE_BOAT); + } +} + +void ABoat::BeginPlay() {} +void ABoat::Draw(s32 playerId) {} +void ABoat::Tick() { + Path2D* waypoint; + struct Actor* paddleBoatActor; + f32 temp_f26; + f32 temp_f28; + f32 temp_f30; + s16 temp_a1; + s32 temp; + s16 var_v1; + Vec3f sp94; + Vec3f sp88; + UNUSED s32 pad; + Vec3f smokePos; + UNUSED s32 pad2; + AnotherSmokeTimer += 1; + if (IsActive == 1) { + temp_f26 = Position[0]; + temp_f28 = Position[1]; + temp_f30 = Position[2]; + update_vehicle_following_waypoint(Position, (s16*) &WaypointIndex, + Speed); + SomeFlags = set_vehicle_render_distance_flags(Position, BOAT_SMOKE_RENDER_DISTANCE, + SomeFlags); + if ((((s16) AnotherSmokeTimer % 10) == 0) && (SomeFlags != 0)) { + smokePos[0] = (f32) ((f64) Position[0] - 30.0); + smokePos[1] = (f32) ((f64) Position[1] + 180.0); + smokePos[2] = (f32) ((f64) Position[2] + 45.0); + adjust_position_by_angle(smokePos, Position, RotY); + //spawn_ferry_smoke(Index, smokePos, 1.1f); + AddSmoke(Index, smokePos, 1.1f); + smokePos[0] = (f32) ((f64) Position[0] + 30.0); + smokePos[1] = (f32) ((f64) Position[1] + 180.0); + smokePos[2] = (f32) ((f64) Position[2] + 45.0); + adjust_position_by_angle(smokePos, Position, RotY); + //spawn_ferry_smoke(Index, smokePos, 1.1f); + AddSmoke(Index, smokePos, 1.1f); + } + if (random_int(100) == 0) { + if (random_int(2) == 0) { + func_800C98B8(Position, Velocity, SOUND_ARG_LOAD(0x19, 0x01, 0x80, 0x47)); + } else { + func_800C98B8(Position, Velocity, SOUND_ARG_LOAD(0x19, 0x01, 0x80, 0x48)); + } + } + sp94[0] = temp_f26; + sp94[1] = temp_f28; + sp94[2] = temp_f30; + waypoint = &gVehicle2DWaypoint[(WaypointIndex + 5) % gVehicle2DWaypointLength]; + sp88[0] = (f32) waypoint->x; + sp88[1] = (f32) D_80162EB0; + sp88[2] = (f32) waypoint->z; + temp_a1 = get_angle_between_waypoints(sp94, sp88); + temp = temp_a1 - RotY; + var_v1 = temp; + if (var_v1 < 0) { + var_v1 = -var_v1; + } + if (var_v1 >= 0x1771) { + if (Speed > 0.2) { + Speed -= 0.04; + } + if (var_v1 >= 0x3D) { + var_v1 = 0x003C; + } + } else { + if (Speed < 2.0) { + Speed += 0.02; + } + if (var_v1 >= 0x1F) { + var_v1 = 0x001E; + } + } + if (temp >= 0x8000) { + RotY -= var_v1; + } else if (temp > 0) { + RotY += var_v1; + } else if (temp < -0x7FFF) { + RotY += var_v1; + } else if (temp < 0) { + RotY -= var_v1; + } + Velocity[0] = Position[0] - temp_f26; + Velocity[1] = Position[1] - temp_f28; + Velocity[2] = Position[2] - temp_f30; + paddleBoatActor = &gActorList[ActorIndex]; + paddleBoatActor->pos[0] = Position[0]; + paddleBoatActor->pos[1] = Position[1]; + paddleBoatActor->pos[2] = Position[2]; + if (gIsMirrorMode != 0) { + paddleBoatActor->rot[1] = -RotY; + } else { + paddleBoatActor->rot[1] = RotY; + } + Velocity[0] = Velocity[0]; + Velocity[1] = Velocity[1]; + Velocity[2] = Velocity[2]; + } +} + +void ABoat::Collision(s32 playerId, Player* player) { + f32 x_diff; + f32 y_diff; + f32 z_diff; + f32 playerX; + f32 playerZ; + f32 playerY; + + if (!((player->effects & 0x01000000)) && (!(player->effects & HIT_BY_ITEM_EFFECT))) { + playerX = player->pos[0]; + playerY = player->pos[1]; + playerZ = player->pos[2]; + if (IsActive == 1) { + x_diff = playerX - Position[0]; + y_diff = playerY - Position[1]; + z_diff = playerZ - Position[2]; + if ((x_diff > -300.0) && (x_diff < 300.0)) { + if ((z_diff > -300.0) && (z_diff < 300.0)) { + if ((func_80006018(Position[0], Position[2], + Velocity[0], Velocity[2], 200.0f, + 60.0f, playerX, playerZ) == 1) && + (y_diff < 60.0)) { + player->soundEffects |= 0x80000; + } + } + } + } + } +} + +s32 ABoat::AddSmoke(size_t ferryIndex, Vec3f pos, f32 velocity) { + s32 objectIndex = add_unused_obj_index(SmokeParticles, &NextParticlePtr, gObjectParticle2_SIZE); + if (objectIndex != NULL_OBJECT_ID) { + init_ferry_smoke(objectIndex, pos, velocity); + } + + return objectIndex; +} \ No newline at end of file diff --git a/src/engine/vehicles/Boat.h b/src/engine/vehicles/Boat.h new file mode 100644 index 000000000..988f498ab --- /dev/null +++ b/src/engine/vehicles/Boat.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include "Vehicle.h" +#include + +extern "C" { +#include "main.h" +#include "vehicles.h" +} + +class AVehicle; // Forward declare + +class ABoat : public AVehicle { + public: + + const char* Type = "mk:boat"; + size_t Index; + bool IsActive; // The paddle wheel boat only shows up if the number of players is < 3 + Vec3f Position; + Vec3f Velocity; + u16 WaypointIndex; + s16 ActorIndex; + f32 Speed; + s16 RotY = 0; + s32 SomeFlags; + + int32_t SmokeParticles[128]; + int32_t NextParticlePtr = 0; + int16_t AnotherSmokeTimer = 0; + int16_t SmokeTimer = 0; + + explicit ABoat(size_t idx, f32 speed, uint32_t waypoint); + + virtual void Spawn() override; + virtual void BeginPlay() override; + virtual void Tick() override; + virtual void Draw(s32 playerId) override; + virtual void Collision(s32 playerId, Player* player) override; + virtual s32 AddSmoke(size_t, Vec3f, f32); + +}; \ No newline at end of file diff --git a/src/engine/vehicles/Bus.cpp b/src/engine/vehicles/Bus.cpp new file mode 100644 index 000000000..2427cf77f --- /dev/null +++ b/src/engine/vehicles/Bus.cpp @@ -0,0 +1,283 @@ +#include +#include "Bus.h" +#include + +extern "C" { +#include "macros.h" +#include "main.h" +#include "defines.h" +#include "code_80005FD0.h" +#include "actors.h" +#include "math_util.h" +#include "sounds.h" +#include "update_objects.h" +#include "render_player.h" +#include "external.h" +extern s8 gPlayerCount; +} + +ABus::ABus(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) { + TrackWaypoint* temp_v0; + u16 waypointOffset; + s32 numWaypoints = gWaypointCountByPathIndex[0]; + + Index = idx; + + waypointOffset = waypoint; + temp_v0 = &path[waypointOffset]; + Position[0] = (f32) temp_v0->posX; + Position[1] = (f32) temp_v0->posY; + Position[2] = (f32) temp_v0->posZ; + ActorIndex = -1; + WaypointIndex = waypointOffset; + Velocity[0] = 0.0f; + Velocity[1] = 0.0f; + Velocity[2] = 0.0f; + if (gModeSelection == TIME_TRIALS) { + SomeType = ((Index - 1) % 3); + } else { + SomeType = random_int(3); + } + SomeMultiplierTheSequel = (f32) ((f64) (f32) (SomeType - 1) * 0.6); + if (((gCCSelection > CC_50) || (gModeSelection == TIME_TRIALS)) && (SomeType == 2)) { + Speed = speedA; + } else { + Speed = speedB; + } + Rotation[0] = 0; + Rotation[2] = 0; + if (D_8016347A == 0) { + Rotation[1] = func_8000D6D0(Position, (s16*) &WaypointIndex, Speed, + SomeMultiplierTheSequel, 0, 3); + } else { + Rotation[1] = + func_8000D940(Position, (s16*) &WaypointIndex, Speed, SomeMultiplierTheSequel, 0); + } + D_801631C8 = 10; +} + +void ABus::Spawn() { + spawn_vehicle_on_road(Position, Rotation, Velocity, WaypointIndex, SomeMultiplierTheSequel, + Speed); + ActorIndex = add_actor_to_empty_slot(Position, Rotation, Velocity, ACTOR_SCHOOL_BUS); +} + +void ABus::BeginPlay() { + +} + +void ABus::Draw(s32 playerId) { + s32 var_v0; + s32 var_s2; + s32 waypointCount; + u16 temp_a1; + + waypointCount = gWaypointCountByPathIndex[0]; + if (!(gPlayers[playerId].unk_094 < 1.6666666666666667)) { + temp_a1 = WaypointIndex; + for (var_v0 = 0; var_v0 < 0x18; var_v0 += 3) { + if (((sSomeNearestWaypoint + var_v0) % waypointCount) == temp_a1) { + D_801634F8[playerId].unk4 = func_800145A8(SomeType, D_80163068[playerId], temp_a1); + return; + } + } + } +} + +void ABus::Tick() { + f32 temp_f0_2; + f32 temp_f0_3; + f32 sp5C; + f32 sp58; + f32 sp54; + f32 temp_f2_2; + s16 var_a1; + s16 thing; + Vec3f sp40; + Vec3f sp34; + + sp5C = Position[0]; + sp58 = Position[1]; + sp54 = Position[2]; + sp40[0] = sp58; + sp40[1] = 0.0f; + sp40[2] = 0.0f; + temp_f0_2 = func_80013C74(SomeType, WaypointIndex); + if (SomeMultiplierTheSequel < temp_f0_2) { + SomeMultiplierTheSequel = SomeMultiplierTheSequel + 0.06; + if (temp_f0_2 < SomeMultiplierTheSequel) { + SomeMultiplierTheSequel = temp_f0_2; + } + } + if (temp_f0_2 < SomeMultiplierTheSequel) { + SomeMultiplierTheSequel = SomeMultiplierTheSequel - 0.06; + if (SomeMultiplierTheSequel < temp_f0_2) { + SomeMultiplierTheSequel = temp_f0_2; + } + } + if (D_8016347A == 0) { + var_a1 = func_8000D6D0(Position, (s16*) &WaypointIndex, Speed, + SomeMultiplierTheSequel, 0, 3); + } else { + var_a1 = func_8000D940(Position, (s16*) &WaypointIndex, Speed, + SomeMultiplierTheSequel, 0); + } + adjust_angle(&Rotation[1], var_a1, 100); + temp_f0_3 = Position[0] - sp5C; + temp_f2_2 = Position[2] - sp54; + sp34[0] = Position[1]; + sp34[1] = 0.0f; + sp34[2] = sqrtf((temp_f0_3 * temp_f0_3) + (temp_f2_2 * temp_f2_2)); + thing = get_angle_between_two_vectors(sp40, sp34); + adjust_angle(&Rotation[0], -thing, 100); + Velocity[0] = Position[0] - sp5C; + Velocity[1] = Position[1] - sp58; + Velocity[2] = Position[2] - sp54; + struct Actor* vehicleActor = &gActorList[ActorIndex]; + vehicleActor->pos[0] = Position[0]; + vehicleActor->pos[1] = Position[1]; + vehicleActor->pos[2] = Position[2]; + vehicleActor->rot[0] = Rotation[0]; + if (gIsMirrorMode != 0) { + vehicleActor->rot[1] = -Rotation[1]; + } else { + vehicleActor->rot[1] = Rotation[1]; + } + vehicleActor->rot[2] = Rotation[2]; + vehicleActor->velocity[0] = Velocity[0]; + vehicleActor->velocity[1] = Velocity[1]; + vehicleActor->velocity[2] = Velocity[2]; +} + +void ABus::Collision(s32 playerId, Player* player) { + f32 temp_f12; + f32 temp_f14; + f32 temp_f22; + + f32 spC4; + f32 spC0; + f32 spBC; + + if (((D_801631E0[playerId] != 1) || ((((player->type & PLAYER_HUMAN) != 0)) && !(player->type & PLAYER_KART_AI))) && + !(player->effects & 0x01000000)) { + + spC4 = player->pos[0]; + spC0 = player->pos[1]; + spBC = player->pos[2]; + + temp_f12 = spC4 - Position[0]; + temp_f22 = spC0 - Position[1]; + temp_f14 = spBC - Position[2]; + + if (((temp_f12) > -100.0) && ((temp_f12) < 100.0)) { + if ((temp_f22 > -20.0) && (temp_f22 < 20.0)) { + + if (((temp_f14) > -100.0) && ((temp_f14) < 100.0)) { + if (func_80006018(Position[0], Position[2], Velocity[0], + Velocity[2], SomeArg3, SomeArg4, spC4, spBC) == (s32) 1) { + player->soundEffects |= REVERSE_SOUND_EFFECT; + } + } + } + } + if ((player->type & PLAYER_HUMAN) && !(player->type & PLAYER_KART_AI)) { + if (((temp_f12) > -300.0) && ((temp_f12) < 300.0) && ((temp_f22 > -20.0)) && (temp_f22 < 20.0) && + (((temp_f14) > -300.0)) && ((temp_f14) < 300.0)) { + if ((D_801631C8 > 0) && (SomeFlags == 0)) { + D_801631C8 -= 1; + SomeFlags |= (RENDER_VEHICLE << playerId); + func_800C9D80(Position, Velocity, SoundBits); + } + } else { + if (SomeFlags != 0) { + SomeFlags &= ~(RENDER_VEHICLE << playerId); + if (SomeFlags == 0) { + D_801631C8 += 1; + func_800C9EF4(Position, SoundBits); + } + } + } + + if (((temp_f12) > -200.0) && ((temp_f12) < 200.0) && ((temp_f22 > -20.0)) && (temp_f22 < 20.0) && + (((temp_f14) > -200.0)) && ((temp_f14) < 200.0)) { + if (!(SomeFlagsTheSequel & ((1 << playerId)))) { + + s32 var_s1 = 0; + u16 path = gWaypointCountByPathIndex[0]; + s32 t1; + s32 t2; + + switch (D_8016347A) { + case 0: + t1 = func_80007BF8(WaypointIndex, gNearestWaypointByPlayerId[playerId], 10, 0, + path); + if ((D_80163270[playerId] == 0) && (t1 > 0) && (player->unk_094 < Speed)) { + var_s1 = 1; + } + if ((D_80163270[playerId] == 1) && (t1 > 0)) { + var_s1 = 1; + } + break; + case 1: + t2 = func_80007BF8(WaypointIndex, gNearestWaypointByPlayerId[playerId], 0, 10, + path); + if (t2 > 0) { + if (random_int(2) == 0) { + // temp_v1_2 = D_80163270[playerId]; + if (D_80163270[playerId] == 0) { + var_s1 = 1; + } + if ((D_80163270[playerId] == 1) && (player->unk_094 < Speed)) { + var_s1 = 1; + } + } else { + SomeFlagsTheSequel |= ((1 << playerId)); + } + } + break; + } + if (var_s1 == 1) { + + u32 soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3B); + + switch (SoundBits) { + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x05): + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3B); + if (random_int(4) == 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3C); + } + break; + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x02): + if (random_int(2) != 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3D); + } else { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3E); + } + break; + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x03): + if (random_int(2) != 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3F); + } else { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x40); + } + break; + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x04): + if (random_int(2) != 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x41); + } else { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x42); + } + break; + } + SomeFlagsTheSequel |= ((1 << playerId)); + func_800C98B8(Position, Velocity, soundBits2); + } + } + } else { + if (SomeFlagsTheSequel & ((1 << playerId))) { + SomeFlagsTheSequel &= ~((1 << playerId)); + } + } + } + } +} diff --git a/src/engine/vehicles/Bus.h b/src/engine/vehicles/Bus.h new file mode 100644 index 000000000..ff75d5aff --- /dev/null +++ b/src/engine/vehicles/Bus.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include "Vehicle.h" +#include + +extern "C" { +#include "main.h" +#include "vehicles.h" +#include "waypoints.h" +#include "sounds.h" +} + +class AVehicle; // Forward declare + +class ABus : public AVehicle { + public: + + const char* Type; + size_t Index; + f32 Speed; + s16 ActorIndex; + Vec3f Position; + Vec3f Velocity; + Vec3s Rotation; + f32 SomeMultiplierTheSequel; + s8 SomeFlagsTheSequel = 0; + u16 WaypointIndex; + s8 SomeFlags = 0; + s16 SomeType; + + f32 SomeArg3 = 55.0f; + f32 SomeArg4 = 12.5f; + u32 SoundBits = SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x03); + + explicit ABus(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint); + + virtual void Spawn() override; + virtual void BeginPlay() override; + virtual void Tick() override; + virtual void Draw(s32 playerId) override; + virtual void Collision(s32 playerId, Player* player) override; +}; \ No newline at end of file diff --git a/src/engine/vehicles/Car.cpp b/src/engine/vehicles/Car.cpp new file mode 100644 index 000000000..f742aaa75 --- /dev/null +++ b/src/engine/vehicles/Car.cpp @@ -0,0 +1,283 @@ +#include +#include "Car.h" +#include + +extern "C" { +#include "macros.h" +#include "main.h" +#include "defines.h" +#include "code_80005FD0.h" +#include "actors.h" +#include "math_util.h" +#include "sounds.h" +#include "update_objects.h" +#include "render_player.h" +#include "external.h" +extern s8 gPlayerCount; +} + +ACar::ACar(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) { + TrackWaypoint* temp_v0; + u16 waypointOffset; + s32 numWaypoints = gWaypointCountByPathIndex[0]; + + Index = idx; + + waypointOffset = waypoint; + temp_v0 = &path[waypointOffset]; + Position[0] = (f32) temp_v0->posX; + Position[1] = (f32) temp_v0->posY; + Position[2] = (f32) temp_v0->posZ; + ActorIndex = -1; + WaypointIndex = waypointOffset; + Velocity[0] = 0.0f; + Velocity[1] = 0.0f; + Velocity[2] = 0.0f; + if (gModeSelection == TIME_TRIALS) { + SomeType = ((Index - 1) % 3); + } else { + SomeType = random_int(3); + } + SomeMultiplierTheSequel = (f32) ((f64) (f32) (SomeType - 1) * 0.6); + if (((gCCSelection > CC_50) || (gModeSelection == TIME_TRIALS)) && (SomeType == 2)) { + Speed = speedA; + } else { + Speed = speedB; + } + Rotation[0] = 0; + Rotation[2] = 0; + if (D_8016347A == 0) { + Rotation[1] = func_8000D6D0(Position, (s16*) &WaypointIndex, Speed, + SomeMultiplierTheSequel, 0, 3); + } else { + Rotation[1] = + func_8000D940(Position, (s16*) &WaypointIndex, Speed, SomeMultiplierTheSequel, 0); + } + D_801631C8 = 10; +} + +void ACar::Spawn() { + spawn_vehicle_on_road(Position, Rotation, Velocity, WaypointIndex, SomeMultiplierTheSequel, + Speed); + ActorIndex = add_actor_to_empty_slot(Position, Rotation, Velocity, ACTOR_CAR); +} + +void ACar::BeginPlay() { + +} + +void ACar::Tick() { + f32 temp_f0_2; + f32 temp_f0_3; + f32 sp5C; + f32 sp58; + f32 sp54; + f32 temp_f2_2; + s16 var_a1; + s16 thing; + Vec3f sp40; + Vec3f sp34; + + sp5C = Position[0]; + sp58 = Position[1]; + sp54 = Position[2]; + sp40[0] = sp58; + sp40[1] = 0.0f; + sp40[2] = 0.0f; + temp_f0_2 = func_80013C74(SomeType, WaypointIndex); + if (SomeMultiplierTheSequel < temp_f0_2) { + SomeMultiplierTheSequel = SomeMultiplierTheSequel + 0.06; + if (temp_f0_2 < SomeMultiplierTheSequel) { + SomeMultiplierTheSequel = temp_f0_2; + } + } + if (temp_f0_2 < SomeMultiplierTheSequel) { + SomeMultiplierTheSequel = SomeMultiplierTheSequel - 0.06; + if (SomeMultiplierTheSequel < temp_f0_2) { + SomeMultiplierTheSequel = temp_f0_2; + } + } + if (D_8016347A == 0) { + var_a1 = func_8000D6D0(Position, (s16*) &WaypointIndex, Speed, + SomeMultiplierTheSequel, 0, 3); + } else { + var_a1 = func_8000D940(Position, (s16*) &WaypointIndex, Speed, + SomeMultiplierTheSequel, 0); + } + adjust_angle(&Rotation[1], var_a1, 100); + temp_f0_3 = Position[0] - sp5C; + temp_f2_2 = Position[2] - sp54; + sp34[0] = Position[1]; + sp34[1] = 0.0f; + sp34[2] = sqrtf((temp_f0_3 * temp_f0_3) + (temp_f2_2 * temp_f2_2)); + thing = get_angle_between_two_vectors(sp40, sp34); + adjust_angle(&Rotation[0], -thing, 100); + Velocity[0] = Position[0] - sp5C; + Velocity[1] = Position[1] - sp58; + Velocity[2] = Position[2] - sp54; + struct Actor* vehicleActor = &gActorList[ActorIndex]; + vehicleActor->pos[0] = Position[0]; + vehicleActor->pos[1] = Position[1]; + vehicleActor->pos[2] = Position[2]; + vehicleActor->rot[0] = Rotation[0]; + if (gIsMirrorMode != 0) { + vehicleActor->rot[1] = -Rotation[1]; + } else { + vehicleActor->rot[1] = Rotation[1]; + } + vehicleActor->rot[2] = Rotation[2]; + vehicleActor->velocity[0] = Velocity[0]; + vehicleActor->velocity[1] = Velocity[1]; + vehicleActor->velocity[2] = Velocity[2]; +} + +void ACar::Draw(s32 playerId) { + s32 var_v0; + s32 var_s2; + s32 waypointCount; + u16 temp_a1; + + waypointCount = gWaypointCountByPathIndex[0]; + if (!(gPlayers[playerId].unk_094 < 1.6666666666666667)) { + temp_a1 = WaypointIndex; + for (var_v0 = 0; var_v0 < 0x18; var_v0 += 3) { + if (((sSomeNearestWaypoint + var_v0) % waypointCount) == temp_a1) { + D_801634F8[playerId].unk4 = func_800145A8(SomeType, D_80163068[playerId], temp_a1); + return; + } + } + } +} + +void ACar::Collision(s32 playerId, Player* player) { + f32 temp_f12; + f32 temp_f14; + f32 temp_f22; + + f32 spC4; + f32 spC0; + f32 spBC; + + if (((D_801631E0[playerId] != 1) || ((((player->type & PLAYER_HUMAN) != 0)) && !(player->type & PLAYER_KART_AI))) && + !(player->effects & 0x01000000)) { + + spC4 = player->pos[0]; + spC0 = player->pos[1]; + spBC = player->pos[2]; + + temp_f12 = spC4 - Position[0]; + temp_f22 = spC0 - Position[1]; + temp_f14 = spBC - Position[2]; + + if (((temp_f12) > -100.0) && ((temp_f12) < 100.0)) { + if ((temp_f22 > -20.0) && (temp_f22 < 20.0)) { + + if (((temp_f14) > -100.0) && ((temp_f14) < 100.0)) { + if (func_80006018(Position[0], Position[2], Velocity[0], + Velocity[2], SomeArg3, SomeArg4, spC4, spBC) == (s32) 1) { + player->soundEffects |= REVERSE_SOUND_EFFECT; + } + } + } + } + if ((player->type & PLAYER_HUMAN) && !(player->type & PLAYER_KART_AI)) { + if (((temp_f12) > -300.0) && ((temp_f12) < 300.0) && ((temp_f22 > -20.0)) && (temp_f22 < 20.0) && + (((temp_f14) > -300.0)) && ((temp_f14) < 300.0)) { + if ((D_801631C8 > 0) && (SomeFlags == 0)) { + D_801631C8 -= 1; + SomeFlags |= (RENDER_VEHICLE << playerId); + func_800C9D80(Position, Velocity, SoundBits); + } + } else { + if (SomeFlags != 0) { + SomeFlags &= ~(RENDER_VEHICLE << playerId); + if (SomeFlags == 0) { + D_801631C8 += 1; + func_800C9EF4(Position, SoundBits); + } + } + } + + if (((temp_f12) > -200.0) && ((temp_f12) < 200.0) && ((temp_f22 > -20.0)) && (temp_f22 < 20.0) && + (((temp_f14) > -200.0)) && ((temp_f14) < 200.0)) { + if (!(SomeFlagsTheSequel & ((1 << playerId)))) { + + s32 var_s1 = 0; + u16 path = gWaypointCountByPathIndex[0]; + s32 t1; + s32 t2; + + switch (D_8016347A) { + case 0: + t1 = func_80007BF8(WaypointIndex, gNearestWaypointByPlayerId[playerId], 10, 0, + path); + if ((D_80163270[playerId] == 0) && (t1 > 0) && (player->unk_094 < Speed)) { + var_s1 = 1; + } + if ((D_80163270[playerId] == 1) && (t1 > 0)) { + var_s1 = 1; + } + break; + case 1: + t2 = func_80007BF8(WaypointIndex, gNearestWaypointByPlayerId[playerId], 0, 10, + path); + if (t2 > 0) { + if (random_int(2) == 0) { + // temp_v1_2 = D_80163270[playerId]; + if (D_80163270[playerId] == 0) { + var_s1 = 1; + } + if ((D_80163270[playerId] == 1) && (player->unk_094 < Speed)) { + var_s1 = 1; + } + } else { + SomeFlagsTheSequel |= ((1 << playerId)); + } + } + break; + } + if (var_s1 == 1) { + + u32 soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3B); + + switch (SoundBits) { + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x05): + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3B); + if (random_int(4) == 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3C); + } + break; + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x02): + if (random_int(2) != 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3D); + } else { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3E); + } + break; + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x03): + if (random_int(2) != 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3F); + } else { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x40); + } + break; + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x04): + if (random_int(2) != 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x41); + } else { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x42); + } + break; + } + SomeFlagsTheSequel |= ((1 << playerId)); + func_800C98B8(Position, Velocity, soundBits2); + } + } + } else { + if (SomeFlagsTheSequel & ((1 << playerId))) { + SomeFlagsTheSequel &= ~((1 << playerId)); + } + } + } + } +} \ No newline at end of file diff --git a/src/engine/vehicles/Car.h b/src/engine/vehicles/Car.h new file mode 100644 index 000000000..8ac7421aa --- /dev/null +++ b/src/engine/vehicles/Car.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include "Vehicle.h" +#include + +extern "C" { +#include "main.h" +#include "vehicles.h" +#include "waypoints.h" +#include "sounds.h" +} + +class AVehicle; // Forward declare + +class ACar : public AVehicle { + public: + + explicit ACar(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint); + + const char* Type; + size_t Index; + f32 Speed; + s16 ActorIndex; + Vec3f Position; + Vec3f Velocity; + Vec3s Rotation; + f32 SomeMultiplierTheSequel; + s8 SomeFlagsTheSequel = 0; + u16 WaypointIndex; + s8 SomeFlags = 0; + s16 SomeType; + + f32 SomeArg3 = 11.5f; + f32 SomeArg4 = 8.5f; + u32 SoundBits = SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x05); + + virtual void Spawn() override; + virtual void BeginPlay() override; + virtual void Tick() override; + virtual void Draw(s32 playerId) override; + virtual void Collision(s32 playerId, Player* player) override; +}; \ No newline at end of file diff --git a/src/engine/vehicles/TankerTruck.cpp b/src/engine/vehicles/TankerTruck.cpp new file mode 100644 index 000000000..4d4de5016 --- /dev/null +++ b/src/engine/vehicles/TankerTruck.cpp @@ -0,0 +1,283 @@ +#include +#include "TankerTruck.h" +#include + +extern "C" { +#include "macros.h" +#include "main.h" +#include "defines.h" +#include "code_80005FD0.h" +#include "actors.h" +#include "math_util.h" +#include "sounds.h" +#include "update_objects.h" +#include "render_player.h" +#include "external.h" +extern s8 gPlayerCount; +} + +ATankerTruck::ATankerTruck(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) { + TrackWaypoint* temp_v0; + u16 waypointOffset; + s32 numWaypoints = gWaypointCountByPathIndex[0]; + + Index = idx; + + waypointOffset = waypoint; + temp_v0 = &path[waypointOffset]; + Position[0] = (f32) temp_v0->posX; + Position[1] = (f32) temp_v0->posY; + Position[2] = (f32) temp_v0->posZ; + ActorIndex = -1; + WaypointIndex = waypointOffset; + Velocity[0] = 0.0f; + Velocity[1] = 0.0f; + Velocity[2] = 0.0f; + if (gModeSelection == TIME_TRIALS) { + SomeType = ((Index - 1) % 3); + } else { + SomeType = random_int(3); + } + SomeMultiplierTheSequel = (f32) ((f64) (f32) (SomeType - 1) * 0.6); + if (((gCCSelection > CC_50) || (gModeSelection == TIME_TRIALS)) && (SomeType == 2)) { + Speed = speedA; + } else { + Speed = speedB; + } + Rotation[0] = 0; + Rotation[2] = 0; + if (D_8016347A == 0) { + Rotation[1] = func_8000D6D0(Position, (s16*) &WaypointIndex, Speed, + SomeMultiplierTheSequel, 0, 3); + } else { + Rotation[1] = + func_8000D940(Position, (s16*) &WaypointIndex, Speed, SomeMultiplierTheSequel, 0); + } + D_801631C8 = 10; +} + +void ATankerTruck::Spawn() { + spawn_vehicle_on_road(Position, Rotation, Velocity, WaypointIndex, SomeMultiplierTheSequel, + Speed); + ActorIndex = add_actor_to_empty_slot(Position, Rotation, Velocity, ACTOR_TANKER_TRUCK); +} + +void ATankerTruck::BeginPlay() { + +} + +void ATankerTruck::Draw(s32 playerId) { + s32 var_v0; + s32 var_s2; + s32 waypointCount; + u16 temp_a1; + + waypointCount = gWaypointCountByPathIndex[0]; + if (!(gPlayers[playerId].unk_094 < 1.6666666666666667)) { + temp_a1 = WaypointIndex; + for (var_v0 = 0; var_v0 < 0x18; var_v0 += 3) { + if (((sSomeNearestWaypoint + var_v0) % waypointCount) == temp_a1) { + D_801634F8[playerId].unk4 = func_800145A8(SomeType, D_80163068[playerId], temp_a1); + return; + } + } + } +} + +void ATankerTruck::Tick() { + f32 temp_f0_2; + f32 temp_f0_3; + f32 sp5C; + f32 sp58; + f32 sp54; + f32 temp_f2_2; + s16 var_a1; + s16 thing; + Vec3f sp40; + Vec3f sp34; + + sp5C = Position[0]; + sp58 = Position[1]; + sp54 = Position[2]; + sp40[0] = sp58; + sp40[1] = 0.0f; + sp40[2] = 0.0f; + temp_f0_2 = func_80013C74(SomeType, WaypointIndex); + if (SomeMultiplierTheSequel < temp_f0_2) { + SomeMultiplierTheSequel = SomeMultiplierTheSequel + 0.06; + if (temp_f0_2 < SomeMultiplierTheSequel) { + SomeMultiplierTheSequel = temp_f0_2; + } + } + if (temp_f0_2 < SomeMultiplierTheSequel) { + SomeMultiplierTheSequel = SomeMultiplierTheSequel - 0.06; + if (SomeMultiplierTheSequel < temp_f0_2) { + SomeMultiplierTheSequel = temp_f0_2; + } + } + if (D_8016347A == 0) { + var_a1 = func_8000D6D0(Position, (s16*) &WaypointIndex, Speed, + SomeMultiplierTheSequel, 0, 3); + } else { + var_a1 = func_8000D940(Position, (s16*) &WaypointIndex, Speed, + SomeMultiplierTheSequel, 0); + } + adjust_angle(&Rotation[1], var_a1, 100); + temp_f0_3 = Position[0] - sp5C; + temp_f2_2 = Position[2] - sp54; + sp34[0] = Position[1]; + sp34[1] = 0.0f; + sp34[2] = sqrtf((temp_f0_3 * temp_f0_3) + (temp_f2_2 * temp_f2_2)); + thing = get_angle_between_two_vectors(sp40, sp34); + adjust_angle(&Rotation[0], -thing, 100); + Velocity[0] = Position[0] - sp5C; + Velocity[1] = Position[1] - sp58; + Velocity[2] = Position[2] - sp54; + struct Actor* vehicleActor = &gActorList[ActorIndex]; + vehicleActor->pos[0] = Position[0]; + vehicleActor->pos[1] = Position[1]; + vehicleActor->pos[2] = Position[2]; + vehicleActor->rot[0] = Rotation[0]; + if (gIsMirrorMode != 0) { + vehicleActor->rot[1] = -Rotation[1]; + } else { + vehicleActor->rot[1] = Rotation[1]; + } + vehicleActor->rot[2] = Rotation[2]; + vehicleActor->velocity[0] = Velocity[0]; + vehicleActor->velocity[1] = Velocity[1]; + vehicleActor->velocity[2] = Velocity[2]; +} + +void ATankerTruck::Collision(s32 playerId, Player* player) { + f32 temp_f12; + f32 temp_f14; + f32 temp_f22; + + f32 spC4; + f32 spC0; + f32 spBC; + + if (((D_801631E0[playerId] != 1) || ((((player->type & PLAYER_HUMAN) != 0)) && !(player->type & PLAYER_KART_AI))) && + !(player->effects & 0x01000000)) { + + spC4 = player->pos[0]; + spC0 = player->pos[1]; + spBC = player->pos[2]; + + temp_f12 = spC4 - Position[0]; + temp_f22 = spC0 - Position[1]; + temp_f14 = spBC - Position[2]; + + if (((temp_f12) > -100.0) && ((temp_f12) < 100.0)) { + if ((temp_f22 > -20.0) && (temp_f22 < 20.0)) { + + if (((temp_f14) > -100.0) && ((temp_f14) < 100.0)) { + if (func_80006018(Position[0], Position[2], Velocity[0], + Velocity[2], SomeArg3, SomeArg4, spC4, spBC) == (s32) 1) { + player->soundEffects |= REVERSE_SOUND_EFFECT; + } + } + } + } + if ((player->type & PLAYER_HUMAN) && !(player->type & PLAYER_KART_AI)) { + if (((temp_f12) > -300.0) && ((temp_f12) < 300.0) && ((temp_f22 > -20.0)) && (temp_f22 < 20.0) && + (((temp_f14) > -300.0)) && ((temp_f14) < 300.0)) { + if ((D_801631C8 > 0) && (SomeFlags == 0)) { + D_801631C8 -= 1; + SomeFlags |= (RENDER_VEHICLE << playerId); + func_800C9D80(Position, Velocity, SoundBits); + } + } else { + if (SomeFlags != 0) { + SomeFlags &= ~(RENDER_VEHICLE << playerId); + if (SomeFlags == 0) { + D_801631C8 += 1; + func_800C9EF4(Position, SoundBits); + } + } + } + + if (((temp_f12) > -200.0) && ((temp_f12) < 200.0) && ((temp_f22 > -20.0)) && (temp_f22 < 20.0) && + (((temp_f14) > -200.0)) && ((temp_f14) < 200.0)) { + if (!(SomeFlagsTheSequel & ((1 << playerId)))) { + + s32 var_s1 = 0; + u16 path = gWaypointCountByPathIndex[0]; + s32 t1; + s32 t2; + + switch (D_8016347A) { + case 0: + t1 = func_80007BF8(WaypointIndex, gNearestWaypointByPlayerId[playerId], 10, 0, + path); + if ((D_80163270[playerId] == 0) && (t1 > 0) && (player->unk_094 < Speed)) { + var_s1 = 1; + } + if ((D_80163270[playerId] == 1) && (t1 > 0)) { + var_s1 = 1; + } + break; + case 1: + t2 = func_80007BF8(WaypointIndex, gNearestWaypointByPlayerId[playerId], 0, 10, + path); + if (t2 > 0) { + if (random_int(2) == 0) { + // temp_v1_2 = D_80163270[playerId]; + if (D_80163270[playerId] == 0) { + var_s1 = 1; + } + if ((D_80163270[playerId] == 1) && (player->unk_094 < Speed)) { + var_s1 = 1; + } + } else { + SomeFlagsTheSequel |= ((1 << playerId)); + } + } + break; + } + if (var_s1 == 1) { + + u32 soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3B); + + switch (SoundBits) { + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x05): + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3B); + if (random_int(4) == 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3C); + } + break; + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x02): + if (random_int(2) != 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3D); + } else { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3E); + } + break; + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x03): + if (random_int(2) != 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3F); + } else { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x40); + } + break; + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x04): + if (random_int(2) != 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x41); + } else { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x42); + } + break; + } + SomeFlagsTheSequel |= ((1 << playerId)); + func_800C98B8(Position, Velocity, soundBits2); + } + } + } else { + if (SomeFlagsTheSequel & ((1 << playerId))) { + SomeFlagsTheSequel &= ~((1 << playerId)); + } + } + } + } +} diff --git a/src/engine/vehicles/TankerTruck.h b/src/engine/vehicles/TankerTruck.h new file mode 100644 index 000000000..961d5a0fb --- /dev/null +++ b/src/engine/vehicles/TankerTruck.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include "Vehicle.h" +#include + +extern "C" { +#include "main.h" +#include "vehicles.h" +#include "waypoints.h" +#include "sounds.h" +} + +class AVehicle; // Forward declare + +class ATankerTruck : public AVehicle { + public: + + const char* Type; + size_t Index; + f32 Speed; + s16 ActorIndex; + Vec3f Position; + Vec3f Velocity; + Vec3s Rotation; + f32 SomeMultiplierTheSequel; + s8 SomeFlagsTheSequel = 0; + u16 WaypointIndex; + s8 SomeFlags = 0; + s16 SomeType; + + f32 SomeArg3 = 55.0f; + f32 SomeArg4 = 12.5f; + u32 SoundBits = SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x03); + + explicit ATankerTruck(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint); + + virtual void Spawn() override; + virtual void BeginPlay() override; + virtual void Tick() override; + virtual void Draw(s32 playerId) override; + virtual void Collision(s32 playerId, Player* player) override; +}; \ No newline at end of file diff --git a/src/engine/vehicles/Train.cpp b/src/engine/vehicles/Train.cpp new file mode 100644 index 000000000..85391ec53 --- /dev/null +++ b/src/engine/vehicles/Train.cpp @@ -0,0 +1,294 @@ + +#include +#include +#include "Train.h" +#include + +extern "C" { +#include "macros.h" +#include "main.h" +#include "defines.h" +#include "code_80005FD0.h" +#include "vehicles.h" +#include "actors.h" +#include "math_util.h" +#include "sounds.h" +#include "update_objects.h" +#include "waypoints.h" +#include "code_80057C60.h" +#include "math_util_2.h" +#include "render_objects.h" +#include "assets/common_data.h" + // #include "common_structs.h" +} + +ATrain::ATrain(size_t idx, size_t numCarriages, f32 speed, uint32_t waypoint) { + u16 waypointOffset; + TrainCarStuff* ptr1; + Path2D* pos; + + Index = idx; + Speed = speed; + + // Set to the default value + std::fill(SmokeParticles, SmokeParticles + 128, NULL_OBJECT_ID); + + for (size_t i = 0; i < numCarriages; i++) { + PassengerCars.push_back(TrainCarStuff()); + } + + // outputs 160 or 392 depending on the train. + // Wraps the value around to always output a valid waypoint. + waypointOffset = waypoint; + + // 120.0f is about the maximum usable value + for (size_t i = 0; i < PassengerCars.size(); i++) { + waypointOffset += 4; + ptr1 = &PassengerCars[i]; + pos = &gVehicle2DWaypoint[waypointOffset]; + set_vehicle_pos_waypoint(ptr1, pos, waypointOffset); + } + // Smaller offset for the tender + waypointOffset += 3; + pos = &gVehicle2DWaypoint[waypointOffset]; + set_vehicle_pos_waypoint(&this->Tender, pos, waypointOffset); + waypointOffset += 4; + pos = &gVehicle2DWaypoint[waypointOffset]; + set_vehicle_pos_waypoint(&Locomotive, pos, waypointOffset); + + // Only use locomotive unless overwritten below. + NumCars = LOCOMOTIVE_ONLY; + + // Spawn all rolling stock in single player mode. + switch (gScreenModeSelection) { + case SCREEN_MODE_1P: // single player + Tender.isActive = 1; + + // clang-format off + // Same line required for matching... + for (size_t i = 0; i < numCarriages; i++) { PassengerCars[i].isActive = 1; } + // clang-format on + + NumCars = NUM_TENDERS + numCarriages; + break; + + // Spawn locomotive, tender, and one passenger car in versus 2/3 player mode. + case SCREEN_MODE_2P_SPLITSCREEN_HORIZONTAL: // multiplayer fall-through + case SCREEN_MODE_2P_SPLITSCREEN_VERTICAL: + if (gModeSelection != GRAND_PRIX) { + Tender.isActive = 1; + PassengerCars[4].isActive = 1; + NumCars = NUM_TENDERS + NUM_2P_PASSENGER_CARS; + } + break; + } + + AnotherSmokeTimer = 0; +} + +void ATrain::Spawn() { + TrainCarStuff* tempLocomotive; + TrainCarStuff* tempTender; + TrainCarStuff* tempPassengerCar; + Vec3s trainCarRot; + s16 trainCarYRot; + f32 origXPos; + f32 origZPos; + + tempLocomotive = &Locomotive; + origXPos = tempLocomotive->position[0]; + origZPos = tempLocomotive->position[2]; + trainCarYRot = update_vehicle_following_waypoint( + tempLocomotive->position, (s16*) &tempLocomotive->waypointIndex, Speed); + tempLocomotive->velocity[0] = tempLocomotive->position[0] - origXPos; + tempLocomotive->velocity[2] = tempLocomotive->position[2] - origZPos; + vec3s_set(trainCarRot, 0, trainCarYRot, 0); + tempLocomotive->actorIndex = add_actor_to_empty_slot(tempLocomotive->position, trainCarRot, + tempLocomotive->velocity, ACTOR_TRAIN_ENGINE); + + tempTender = &Tender; + if (tempTender->isActive == 1) { + origXPos = tempTender->position[0]; + origZPos = tempTender->position[2]; + trainCarYRot = update_vehicle_following_waypoint( + tempTender->position, (s16*) &tempTender->waypointIndex, Speed); + tempTender->velocity[0] = tempTender->position[0] - origXPos; + tempTender->velocity[2] = tempTender->position[2] - origZPos; + vec3s_set(trainCarRot, 0, trainCarYRot, 0); + tempTender->actorIndex = add_actor_to_empty_slot(tempTender->position, trainCarRot, + tempTender->velocity, ACTOR_TRAIN_TENDER); + } + + for (size_t i = 0; i < PassengerCars.size(); i++) { + tempPassengerCar = &PassengerCars[i]; + if (tempPassengerCar->isActive == 1) { + origXPos = tempPassengerCar->position[0]; + origZPos = tempPassengerCar->position[2]; + trainCarYRot = update_vehicle_following_waypoint(tempPassengerCar->position, + (s16*) &tempPassengerCar->waypointIndex, + Speed); + tempPassengerCar->velocity[0] = tempPassengerCar->position[0] - origXPos; + tempPassengerCar->velocity[2] = tempPassengerCar->position[2] - origZPos; + vec3s_set(trainCarRot, 0, trainCarYRot, 0); + tempPassengerCar->actorIndex = + add_actor_to_empty_slot(tempPassengerCar->position, trainCarRot, tempPassengerCar->velocity, + ACTOR_TRAIN_PASSENGER_CAR); + } + } +} + +void ATrain::BeginPlay() { +} + +void ATrain::SyncComponents(TrainCarStuff* trainCar, s16 orientationY) { + struct TrainCar* trainCarActor; + + //! @todo: Change actorIndex to ptr to TrainCar actor + trainCarActor = (struct TrainCar*) &gActorList[trainCar->actorIndex]; + trainCarActor->pos[0] = trainCar->position[0]; + trainCarActor->pos[1] = trainCar->position[1]; + trainCarActor->pos[2] = trainCar->position[2]; + if (gIsMirrorMode != 0) { + trainCarActor->rot[1] = -orientationY; + } else { + trainCarActor->rot[1] = orientationY; + } + trainCarActor->velocity[0] = trainCar->velocity[0]; + trainCarActor->velocity[2] = trainCar->velocity[2]; +} + +void ATrain::Tick() { + f32 temp_f20; + TrainCarStuff* car; + u16 oldWaypointIndex; + s16 orientationYUpdate; + f32 temp_f22; + s32 j; + Vec3f smokePos; + + AnotherSmokeTimer += 1; + + oldWaypointIndex = (u16) Locomotive.waypointIndex; + + temp_f20 = Locomotive.position[0]; + temp_f22 = Locomotive.position[2]; + + orientationYUpdate = update_vehicle_following_waypoint( + Locomotive.position, (s16*) &Locomotive.waypointIndex, Speed); + + Locomotive.velocity[0] = Locomotive.position[0] - temp_f20; + Locomotive.velocity[2] = Locomotive.position[2] - temp_f22; + + sync_train_components(&Locomotive, orientationYUpdate); + + if ((oldWaypointIndex != Locomotive.waypointIndex) && + ((Locomotive.waypointIndex == 0x00BE) || + (Locomotive.waypointIndex == 0x0140))) { // play crossing bell sound + func_800C98B8(Locomotive.position, Locomotive.velocity, + SOUND_ARG_LOAD(0x19, 0x01, 0x80, 0x0E)); + } else if (random_int(100) == 0) { // play train whistle sound + func_800C98B8(Locomotive.position, Locomotive.velocity, + SOUND_ARG_LOAD(0x19, 0x01, 0x80, 0x0D)); + } + + SomeFlags = set_vehicle_render_distance_flags( + Locomotive.position, TRAIN_SMOKE_RENDER_DISTANCE, SomeFlags); + // Renders locomotive smoke on all screens if any player is within range. + if ((((s16) AnotherSmokeTimer % 5) == 0) && (SomeFlags != 0)) { + smokePos[0] = Locomotive.position[0]; + smokePos[1] = (f32) ((f64) Locomotive.position[1] + 65.0); + smokePos[2] = (f32) ((f64) Locomotive.position[2] + 25.0); + adjust_position_by_angle(smokePos, Locomotive.position, orientationYUpdate); + //spawn_train_smoke(Index, smokePos, 1.1f); + printf("\nSMOKE HERE: %d\n\n", Index); + AddSmoke(Index, smokePos, 1.1f); + } + + car = &Tender; + + if (car->isActive == 1) { + temp_f20 = car->position[0]; + temp_f22 = car->position[2]; + orientationYUpdate = + update_vehicle_following_waypoint(car->position, (s16*) &car->waypointIndex, Speed); + car->velocity[0] = car->position[0] - temp_f20; + car->velocity[2] = car->position[2] - temp_f22; + sync_train_components(car, orientationYUpdate); + } + + for (j = 0; j < PassengerCars.size(); j++) { + car = &PassengerCars[j]; + if (car->isActive == 1) { + temp_f20 = car->position[0]; + temp_f22 = car->position[2]; + + orientationYUpdate = + update_vehicle_following_waypoint(car->position, (s16*) &car->waypointIndex, Speed); + car->velocity[0] = car->position[0] - temp_f20; + car->velocity[2] = car->position[2] - temp_f22; + sync_train_components(car, orientationYUpdate); + } + } +} + +void ATrain::Collision(s32 playerId, Player* player) { + TrainCarStuff* trainCar; + f32 playerPosX; + f32 playerPosZ; + f32 x_dist; + f32 z_dist; + s32 trainIndex; + + if (D_801631E0[playerId] != 1) { + if (!(player->effects & 0x01000000)) { + playerPosX = player->pos[0]; + playerPosZ = player->pos[2]; + trainCar = &Locomotive; + x_dist = playerPosX - trainCar->position[0]; + z_dist = playerPosZ - trainCar->position[2]; + if ((x_dist > -100.0) && (x_dist < 100.0)) { + if ((z_dist > -100.0) && (z_dist < 100.0)) { + if (func_80006018(trainCar->position[0], trainCar->position[2], trainCar->velocity[0], + trainCar->velocity[2], 60.0f, 20.0f, playerPosX, playerPosZ) == 1) { + player->soundEffects |= REVERSE_SOUND_EFFECT; + } + trainCar = &Tender; + if (trainCar->isActive == 1) { + if (func_80006018(trainCar->position[0], trainCar->position[2], trainCar->velocity[0], + trainCar->velocity[2], 30.0f, 20.0f, playerPosX, playerPosZ) == 1) { + player->soundEffects |= REVERSE_SOUND_EFFECT; + } + } + } + } + + for (size_t i = 0; i < PassengerCars.size(); i++) { + trainCar = &PassengerCars[i]; + x_dist = playerPosX - trainCar->position[0]; + z_dist = playerPosZ - trainCar->position[2]; + if (trainCar->isActive == 1) { + if ((x_dist > -100.0) && (x_dist < 100.0)) { + if ((z_dist > -100.0) && (z_dist < 100.0)) { + if (func_80006018(trainCar->position[0], trainCar->position[2], trainCar->velocity[0], + trainCar->velocity[2], 30.0f, 20.0f, playerPosX, playerPosZ) == 1) { + player->soundEffects |= REVERSE_SOUND_EFFECT; + } + } + } + } + } + } + } +} + + +void ATrain::Draw(s32 playerId) { +} + +s32 ATrain::AddSmoke(s32 trainIndex, Vec3f pos, f32 velocity) { + s32 objectIndex = add_unused_obj_index(SmokeParticles, &NextParticlePtr, gObjectParticle2_SIZE); + if (objectIndex != NULL_OBJECT_ID) { + init_train_smoke(objectIndex, pos, velocity); + } + return objectIndex; +} diff --git a/src/engine/vehicles/Train.h b/src/engine/vehicles/Train.h new file mode 100644 index 000000000..9b733bad3 --- /dev/null +++ b/src/engine/vehicles/Train.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include "Vehicle.h" +#include + +extern "C" { +#include "main.h" +#include "vehicles.h" +} + +class AVehicle; // Forward declare + +class ATrain : public AVehicle { + public: + + TrainCarStuff Locomotive; + TrainCarStuff Tender; + std::vector PassengerCars; + f32 Speed; // 120.0f is about the maximum usable value + s32 SomeFlags; + f32 SomeMultiplier; + size_t NumCars; // Non-locomotive car count? + + const char* Type = "mk:train"; + size_t Index; // Spawns the train in halves of the train path + + int32_t SmokeParticles[128]; + int32_t NextParticlePtr = 0; + int16_t AnotherSmokeTimer = 0; + int16_t SmokeTimer = 0; + + explicit ATrain(size_t idx, size_t numCarriages, f32 speed, uint32_t waypoint); + + virtual void Spawn() override; + virtual void BeginPlay() override; + virtual void Tick() override; + virtual void Draw(s32 playerId) override; + virtual void Collision(s32 playerId, Player* player) override; + s32 AddSmoke(s32 trainIndex, Vec3f pos, f32 velocity); + void SyncComponents(TrainCarStuff* trainCar, s16 orientationY); +}; \ No newline at end of file diff --git a/src/engine/vehicles/Truck.cpp b/src/engine/vehicles/Truck.cpp new file mode 100644 index 000000000..06b0a5a45 --- /dev/null +++ b/src/engine/vehicles/Truck.cpp @@ -0,0 +1,300 @@ +#include +#include "Truck.h" +#include + +extern "C" { +#include "macros.h" +#include "main.h" +#include "defines.h" +#include "code_80005FD0.h" +#include "actors.h" +#include "math_util.h" +#include "sounds.h" +#include "update_objects.h" +#include "render_player.h" +#include "external.h" +extern s8 gPlayerCount; +} + +ATruck::ATruck(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) { + TrackWaypoint* temp_v0; + u16 waypointOffset; + s32 numWaypoints = gWaypointCountByPathIndex[0]; + + Index = idx; + + waypointOffset = waypoint; + temp_v0 = &path[waypointOffset]; + Position[0] = (f32) temp_v0->posX; + Position[1] = (f32) temp_v0->posY; + Position[2] = (f32) temp_v0->posZ; + ActorIndex = -1; + WaypointIndex = waypointOffset; + Velocity[0] = 0.0f; + Velocity[1] = 0.0f; + Velocity[2] = 0.0f; + if (gModeSelection == TIME_TRIALS) { + SomeType = ((Index - 1) % 3); + } else { + SomeType = random_int(3); + } + SomeMultiplierTheSequel = (f32) ((f64) (f32) (SomeType - 1) * 0.6); + if (((gCCSelection > CC_50) || (gModeSelection == TIME_TRIALS)) && (SomeType == 2)) { + Speed = speedA; + } else { + Speed = speedB; + } + Rotation[0] = 0; + Rotation[2] = 0; + if (D_8016347A == 0) { + Rotation[1] = func_8000D6D0(Position, (s16*) &WaypointIndex, Speed, + SomeMultiplierTheSequel, 0, 3); + } else { + Rotation[1] = + func_8000D940(Position, (s16*) &WaypointIndex, Speed, SomeMultiplierTheSequel, 0); + } + D_801631C8 = 10; +} + +void ATruck::Spawn() { + spawn_vehicle_on_road(Position, Rotation, Velocity, WaypointIndex, SomeMultiplierTheSequel, + Speed); + ActorIndex = add_actor_to_empty_slot(Position, Rotation, Velocity, ACTOR_BOX_TRUCK); + //if (Compare(Dict[Type], "mk:bus")) { + // spawn_vehicle_on_road(Position, Rotation, Velocity, WaypointIndex, SomeMultiplierTheSequel, Speed); + // ActorIndex = add_actor_to_empty_slot(Position, Rotation, + // Velocity, ACTOR_SCHOOL_BUS); + //} + // if (Compare(Dict[Type], "mk:tanker")) { + // spawn_vehicle_on_road(tempTankerTruck); + // tempTankerTruck->actorIndex = + // add_actor_to_empty_slot(tempTankerTruck->position, tempTankerTruck->rotation, + // tempTankerTruck->velocity, ACTOR_TANKER_TRUCK); + // } + // if (Compare(Dict[Type], "mk:car")) { + // tempCar = &gCarList[loopIndex]; + // spawn_vehicle_on_road(tempCar); + // tempCar->actorIndex = + // add_actor_to_empty_slot(tempCar->position, tempCar->rotation, tempCar->velocity, ACTOR_CAR); + // } +} + +void ATruck::BeginPlay() { + +} + +void ATruck::Draw(s32 playerId) { + s32 var_v0; + s32 var_s2; + s32 waypointCount; + u16 temp_a1; + + waypointCount = gWaypointCountByPathIndex[0]; + if (!(gPlayers[playerId].unk_094 < 1.6666666666666667)) { + temp_a1 = WaypointIndex; + for (var_v0 = 0; var_v0 < 0x18; var_v0 += 3) { + if (((sSomeNearestWaypoint + var_v0) % waypointCount) == temp_a1) { + D_801634F8[playerId].unk4 = func_800145A8(SomeType, D_80163068[playerId], temp_a1); + return; + } + } + } +} + +void ATruck::Tick() { + f32 temp_f0_2; + f32 temp_f0_3; + f32 sp5C; + f32 sp58; + f32 sp54; + f32 temp_f2_2; + s16 var_a1; + s16 thing; + Vec3f sp40; + Vec3f sp34; + + sp5C = Position[0]; + sp58 = Position[1]; + sp54 = Position[2]; + sp40[0] = sp58; + sp40[1] = 0.0f; + sp40[2] = 0.0f; + temp_f0_2 = func_80013C74(SomeType, WaypointIndex); + if (SomeMultiplierTheSequel < temp_f0_2) { + SomeMultiplierTheSequel = SomeMultiplierTheSequel + 0.06; + if (temp_f0_2 < SomeMultiplierTheSequel) { + SomeMultiplierTheSequel = temp_f0_2; + } + } + if (temp_f0_2 < SomeMultiplierTheSequel) { + SomeMultiplierTheSequel = SomeMultiplierTheSequel - 0.06; + if (SomeMultiplierTheSequel < temp_f0_2) { + SomeMultiplierTheSequel = temp_f0_2; + } + } + if (D_8016347A == 0) { + var_a1 = func_8000D6D0(Position, (s16*) &WaypointIndex, Speed, + SomeMultiplierTheSequel, 0, 3); + } else { + var_a1 = func_8000D940(Position, (s16*) &WaypointIndex, Speed, + SomeMultiplierTheSequel, 0); + } + adjust_angle(&Rotation[1], var_a1, 100); + temp_f0_3 = Position[0] - sp5C; + temp_f2_2 = Position[2] - sp54; + sp34[0] = Position[1]; + sp34[1] = 0.0f; + sp34[2] = sqrtf((temp_f0_3 * temp_f0_3) + (temp_f2_2 * temp_f2_2)); + thing = get_angle_between_two_vectors(sp40, sp34); + adjust_angle(&Rotation[0], -thing, 100); + Velocity[0] = Position[0] - sp5C; + Velocity[1] = Position[1] - sp58; + Velocity[2] = Position[2] - sp54; + struct Actor* vehicleActor = &gActorList[ActorIndex]; + vehicleActor->pos[0] = Position[0]; + vehicleActor->pos[1] = Position[1]; + vehicleActor->pos[2] = Position[2]; + vehicleActor->rot[0] = Rotation[0]; + if (gIsMirrorMode != 0) { + vehicleActor->rot[1] = -Rotation[1]; + } else { + vehicleActor->rot[1] = Rotation[1]; + } + vehicleActor->rot[2] = Rotation[2]; + vehicleActor->velocity[0] = Velocity[0]; + vehicleActor->velocity[1] = Velocity[1]; + vehicleActor->velocity[2] = Velocity[2]; +} + +void ATruck::Collision(s32 playerId, Player* player) { + f32 temp_f12; + f32 temp_f14; + f32 temp_f22; + + f32 spC4; + f32 spC0; + f32 spBC; + + if (((D_801631E0[playerId] != 1) || ((((player->type & PLAYER_HUMAN) != 0)) && !(player->type & PLAYER_KART_AI))) && + !(player->effects & 0x01000000)) { + + spC4 = player->pos[0]; + spC0 = player->pos[1]; + spBC = player->pos[2]; + + temp_f12 = spC4 - Position[0]; + temp_f22 = spC0 - Position[1]; + temp_f14 = spBC - Position[2]; + + if (((temp_f12) > -100.0) && ((temp_f12) < 100.0)) { + if ((temp_f22 > -20.0) && (temp_f22 < 20.0)) { + + if (((temp_f14) > -100.0) && ((temp_f14) < 100.0)) { + if (func_80006018(Position[0], Position[2], Velocity[0], + Velocity[2], SomeArg3, SomeArg4, spC4, spBC) == (s32) 1) { + player->soundEffects |= REVERSE_SOUND_EFFECT; + } + } + } + } + if ((player->type & PLAYER_HUMAN) && !(player->type & PLAYER_KART_AI)) { + if (((temp_f12) > -300.0) && ((temp_f12) < 300.0) && ((temp_f22 > -20.0)) && (temp_f22 < 20.0) && + (((temp_f14) > -300.0)) && ((temp_f14) < 300.0)) { + if ((D_801631C8 > 0) && (SomeFlags == 0)) { + D_801631C8 -= 1; + SomeFlags |= (RENDER_VEHICLE << playerId); + func_800C9D80(Position, Velocity, SoundBits); + } + } else { + if (SomeFlags != 0) { + SomeFlags &= ~(RENDER_VEHICLE << playerId); + if (SomeFlags == 0) { + D_801631C8 += 1; + func_800C9EF4(Position, SoundBits); + } + } + } + + if (((temp_f12) > -200.0) && ((temp_f12) < 200.0) && ((temp_f22 > -20.0)) && (temp_f22 < 20.0) && + (((temp_f14) > -200.0)) && ((temp_f14) < 200.0)) { + if (!(SomeFlagsTheSequel & ((1 << playerId)))) { + + s32 var_s1 = 0; + u16 path = gWaypointCountByPathIndex[0]; + s32 t1; + s32 t2; + + switch (D_8016347A) { + case 0: + t1 = func_80007BF8(WaypointIndex, gNearestWaypointByPlayerId[playerId], 10, 0, + path); + if ((D_80163270[playerId] == 0) && (t1 > 0) && (player->unk_094 < Speed)) { + var_s1 = 1; + } + if ((D_80163270[playerId] == 1) && (t1 > 0)) { + var_s1 = 1; + } + break; + case 1: + t2 = func_80007BF8(WaypointIndex, gNearestWaypointByPlayerId[playerId], 0, 10, + path); + if (t2 > 0) { + if (random_int(2) == 0) { + // temp_v1_2 = D_80163270[playerId]; + if (D_80163270[playerId] == 0) { + var_s1 = 1; + } + if ((D_80163270[playerId] == 1) && (player->unk_094 < Speed)) { + var_s1 = 1; + } + } else { + SomeFlagsTheSequel |= ((1 << playerId)); + } + } + break; + } + if (var_s1 == 1) { + + u32 soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3B); + + switch (SoundBits) { + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x05): + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3B); + if (random_int(4) == 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3C); + } + break; + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x02): + if (random_int(2) != 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3D); + } else { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3E); + } + break; + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x03): + if (random_int(2) != 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3F); + } else { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x40); + } + break; + case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x04): + if (random_int(2) != 0) { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x41); + } else { + soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x42); + } + break; + } + SomeFlagsTheSequel |= ((1 << playerId)); + func_800C98B8(Position, Velocity, soundBits2); + } + } + } else { + if (SomeFlagsTheSequel & ((1 << playerId))) { + SomeFlagsTheSequel &= ~((1 << playerId)); + } + } + } + } +} diff --git a/src/engine/vehicles/Truck.h b/src/engine/vehicles/Truck.h new file mode 100644 index 000000000..8781feaad --- /dev/null +++ b/src/engine/vehicles/Truck.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include "Vehicle.h" +#include + +extern "C" { +#include "main.h" +#include "vehicles.h" +#include "waypoints.h" +#include "sounds.h" +} + +class AVehicle; // Forward declare + +class ATruck : public AVehicle { + public: + + const char* Type; + size_t Index; + f32 Speed; + s16 ActorIndex; + Vec3f Position; + Vec3f Velocity; + Vec3s Rotation; + f32 SomeMultiplierTheSequel; + s8 SomeFlagsTheSequel = 0; + u16 WaypointIndex; + s8 SomeFlags = 0; + s16 SomeType; + + f32 SomeArg3 = 55.0f; + f32 SomeArg4 = 12.5f; + u32 SoundBits = SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x03); + + explicit ATruck(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint); + + virtual void Spawn() override; + virtual void BeginPlay() override; + virtual void Tick() override; + virtual void Draw(s32 playerId) override; + virtual void Collision(s32 playerId, Player* player) override; +}; \ No newline at end of file diff --git a/src/engine/vehicles/Utils.cpp b/src/engine/vehicles/Utils.cpp new file mode 100644 index 000000000..d2a3ece57 --- /dev/null +++ b/src/engine/vehicles/Utils.cpp @@ -0,0 +1,12 @@ +#include +#include "Utils.h" + +extern "C" { +#include "macros.h" +#include "defines.h" +#include "code_80005FD0.h" +} + +uint32_t CalculateWaypointDistribution(size_t i, uint32_t numVehicles, size_t numWaypoints, uint32_t centerWaypoint) { + return (uint32_t)(((i * numWaypoints) / numVehicles) + centerWaypoint) % numWaypoints; +} diff --git a/src/engine/vehicles/Utils.h b/src/engine/vehicles/Utils.h new file mode 100644 index 000000000..e71c4a288 --- /dev/null +++ b/src/engine/vehicles/Utils.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +uint32_t CalculateWaypointDistribution(size_t i, uint32_t numVehicles, size_t numWaypoints, uint32_t centerWaypoint); diff --git a/src/engine/vehicles/Vehicle.cpp b/src/engine/vehicles/Vehicle.cpp new file mode 100644 index 000000000..6c0890511 --- /dev/null +++ b/src/engine/vehicles/Vehicle.cpp @@ -0,0 +1,19 @@ +#include "Vehicle.h" + + +AVehicle::AVehicle() {} + +void AVehicle::Spawn() { +} + +void AVehicle::BeginPlay() { +} + +void AVehicle::Tick() { +} + +void AVehicle::Draw(s32 playerId) { +} + +void AVehicle::Collision(s32 playerId, Player* player) { +} diff --git a/src/engine/vehicles/Vehicle.h b/src/engine/vehicles/Vehicle.h new file mode 100644 index 000000000..0b79d06aa --- /dev/null +++ b/src/engine/vehicles/Vehicle.h @@ -0,0 +1,27 @@ +#ifndef VEHICLE_H +#define VEHICLE_H + +#include + +extern "C" { +#include "common_structs.h" +} + +// Base class +class AVehicle { +public: + virtual ~AVehicle() = default; // Virtual destructor for proper cleanup in derived classes + + explicit AVehicle(); + + const char* Type; + uint8_t uuid[16]; + + virtual void Spawn(); + virtual void BeginPlay(); + virtual void Tick(); + virtual void Draw(s32 playerId); + virtual void Collision(s32 playerId, Player* player); +}; + +#endif // VEHICLE_H \ No newline at end of file diff --git a/src/port/Game.cpp b/src/port/Game.cpp index 34ab164b2..589f2863c 100644 --- a/src/port/Game.cpp +++ b/src/port/Game.cpp @@ -27,6 +27,10 @@ #include "engine/courses/PodiumCeremony.h" +#include "engine/TrainCrossing.h" + +#include "Smoke.h" + extern "C" { #include "main.h" #include "audio/load.h" @@ -130,10 +134,15 @@ void CustomEngineInit() { /* Set default course; mario raceway */ gWorldInstance.CurrentCourse = gMarioRaceway; gWorldInstance.CurrentCup = flower; - gWorldInstance.CurrentCup->CursorPosition = 3; + gWorldInstance.CurrentCup->CursorPosition = 2; } extern "C" { + +World* GetWorld(void) { + return &gWorldInstance; +} + u32 WorldNextCup(void) { return gWorldInstance.NextCup(); } @@ -191,15 +200,78 @@ void CourseManager_SpawnVehicles() { } } -void CourseManager_UpdateVehicles() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->UpdateVehicles(); + void CourseManager_VehiclesSpawn() { + for (auto& vehicle : gWorldInstance.Vehicles) { + if (vehicle) { + vehicle->Spawn(); + } + } + } + + void CourseManager_VehiclesTick() { + for (auto& vehicle : gWorldInstance.Vehicles) { + if (vehicle) { + vehicle->Tick(); + } + } + } + + void CourseManager_VehiclesCollision(s32 playerId, Player* player) { + for (auto& vehicle : gWorldInstance.Vehicles) { + if (vehicle) { + vehicle->Collision(playerId, player); + } + } + } + + void CourseManager_RenderTrucks(s32 playerId) { + for (auto& vehicle : gWorldInstance.Vehicles) { + if (vehicle) { + vehicle->Draw(playerId); + } + } } } -void CourseManager_LoadTextures() { - if (gWorldInstance.CurrentCourse) { - gWorldInstance.CurrentCourse->LoadTextures(); + void CourseManager_ResetVehicles(void) { + gWorldInstance.ResetVehicles(); + } + + void CourseManager_CrossingTrigger() { + for (auto& crossing : gWorldInstance.Crossings) { + if (crossing) { + crossing->CrossingTrigger(); + } + } + } + + void CourseManager_AICrossingBehaviour(s32 playerId) { + for (auto& crossing : gWorldInstance.Crossings) { + if (crossing) { + crossing->AICrossingBehaviour(playerId); + } + } + } + + s32 CourseManager_GetCrossingOnTriggered(uintptr_t* crossing) { + TrainCrossing* ptr = (TrainCrossing*) crossing; + if (ptr) { + return ptr->OnTriggered; + } + } + + void CourseManager_TrainSmokeTick(void) { + TrainSmokeTick(); + } + + void CourseManager_TrainSmokeDraw(s32 cameraId) { + TrainSmokeDraw(cameraId); + } + + void CourseManager_LoadTextures() { + if (gWorldInstance.CurrentCourse) { + gWorldInstance.CurrentCourse->LoadTextures(); + } } } @@ -334,9 +406,10 @@ size_t GetCupCursorPosition() { return gWorldInstance.CurrentCup->CursorPosition; } -void SetCupCursorPosition(size_t position) { - gWorldInstance.CurrentCup->CursorPosition = position; -} + void SetCupCursorPosition(size_t position) { + gWorldInstance.CurrentCup->SetCourse(position); + //gWorldInstance.CurrentCup->CursorPosition = position; + } size_t GetCupSize() { return gWorldInstance.CurrentCup->GetSize(); diff --git a/src/racing/actors.c b/src/racing/actors.c index 6dfae331b..8452c0c78 100644 --- a/src/racing/actors.c +++ b/src/racing/actors.c @@ -817,8 +817,8 @@ UNUSED void func_8029AE14() { #include "actors/falling_rock/render.inc.c" -void spawn_piranha_plants(const char* spawnData) { - struct ActorSpawnData* temp_s0 = (struct ActorSpawnData*) LOAD_ASSET(spawnData); +void spawn_piranha_plants(struct ActorSpawnData* spawnData) { + struct ActorSpawnData* temp_s0 = spawnData; struct PiranhaPlant* temp_v1; UNUSED s32 pad; Vec3f startingPos; @@ -848,7 +848,7 @@ void spawn_piranha_plants(const char* spawnData) { } void spawn_palm_trees(const char* spawnData) { - struct ActorSpawnData* temp_s0 = (struct ActorSpawnData*) LOAD_ASSET(spawnData); + struct ActorSpawnData* temp_s0 = spawnData; struct PalmTree* temp_v1; Vec3f startingPos; Vec3f startingVelocity; @@ -876,7 +876,7 @@ void spawn_palm_trees(const char* spawnData) { // Trees, cacti, shrubs, etc. //! @todo actorType needs to be passed into this function for flexibility -void spawn_foliage(const char* actor) { +void spawn_foliage(struct ActorSpawnData* actor) { UNUSED s32 pad[4]; Vec3f position; Vec3f velocity; @@ -884,9 +884,7 @@ void spawn_foliage(const char* actor) { UNUSED s16 pad2; s16 actorType = 0; struct Actor* temp_s0; - struct ActorSpawnData* var_s3; - - var_s3 = (struct ActorSpawnData*) LOAD_ASSET(actor); + struct ActorSpawnData* var_s3 = actor; vec3f_set(velocity, 0.0f, 0.0f, 0.0f); rotation[0] = 0x4000; rotation[1] = 0; @@ -947,18 +945,13 @@ void spawn_foliage(const char* actor) { } } -void spawn_all_item_boxes(const char* spawnData) { +void spawn_all_item_boxes(struct ActorSpawnData* spawnData) { s16 temp_s1; f32 temp_f0; Vec3f startingPos; Vec3f startingVelocity; Vec3s startingRot; - struct ActorSpawnData* temp_s0; - if (GetCourse() == GetTestCourse()) { - temp_s0 = (struct ActorSpawnData*) spawnData; - } else { - temp_s0 = (struct ActorSpawnData*) LOAD_ASSET(spawnData); - } + struct ActorSpawnData* temp_s0 = spawnData; // struct ItemBox *itemBox; if ((gModeSelection == TIME_TRIALS) || (gPlaceItemBoxes == 0)) { @@ -1209,7 +1202,10 @@ void init_actors_and_load_textures(void) { init_red_shell_texture(); destroy_all_actors(); spawn_course_actors(); - spawn_course_vehicles(); + + CourseManager_VehiclesSpawn(); + + // spawn_course_vehicles(); } void play_sound_before_despawn(struct Actor* actor) { diff --git a/src/racing/actors.h b/src/racing/actors.h index 38ccb5c2a..968bf7264 100644 --- a/src/racing/actors.h +++ b/src/racing/actors.h @@ -67,13 +67,13 @@ void render_actor_train_engine(Camera*, struct TrainCar*); void render_actor_train_tender(Camera*, struct TrainCar*); void render_actor_train_passenger_car(Camera*, struct TrainCar*); void render_actor_falling_rock(Camera*, struct FallingRock*); -void spawn_piranha_plants(const char*); -void spawn_palm_trees(const char*); +void spawn_piranha_plants(struct ActorSpawnData*); +void spawn_palm_trees(struct ActorSpawnData*); void func_8029CF0C(struct ActorSpawnData*, struct FallingRock*); -void spawn_falling_rocks(const char*); +void spawn_falling_rocks(struct ActorSpawnData*); void update_actor_falling_rocks(struct FallingRock*); -void spawn_foliage(const char*); -void spawn_all_item_boxes(const char*); +void spawn_foliage(struct ActorSpawnData*); +void spawn_all_item_boxes(struct ActorSpawnData*); void init_kiwano_fruit(void); void destroy_all_actors(void); void spawn_course_actors(void); diff --git a/src/racing/race_logic.c b/src/racing/race_logic.c index 580e8fc6a..f69a50bdc 100644 --- a/src/racing/race_logic.c +++ b/src/racing/race_logic.c @@ -149,6 +149,7 @@ void func_8028E3A0(void) { } else { D_800DC544++; SetCupCursorPosition(GetCupCursorPosition() + 1); + SetCourseFromCup(); gCourseIndexInCup++; gGotoMode = RACING; } @@ -156,6 +157,7 @@ void func_8028E3A0(void) { D_800DC544++; gCourseIndexInCup++; SetCupCursorPosition(GetCupCursorPosition() + 1); + SetCourseFromCup(); gGotoMode = RACING; } } diff --git a/src/racing/render_courses.c b/src/racing/render_courses.c index 3b4fd6f55..07ab94a11 100644 --- a/src/racing/render_courses.c +++ b/src/racing/render_courses.c @@ -50,14 +50,8 @@ s32 func_80290C20(Camera* camera) { return 0; } -void parse_course_displaylists(const char* asset) { - TrackSections* section; - - if (GetCourse() == GetTestCourse()) { - section = (TrackSections*) asset; - } else { - section = (TrackSections*) LOAD_ASSET(asset); - } +void parse_course_displaylists(TrackSectionsI* asset) { + TrackSections* section = (TrackSections*) asset; while (section->addr != 0) { if (section->flags & 0x8000) { diff --git a/src/racing/render_courses.h b/src/racing/render_courses.h index 3ae4d5337..dfb05c58b 100644 --- a/src/racing/render_courses.h +++ b/src/racing/render_courses.h @@ -13,7 +13,7 @@ typedef struct { void func_8029122C(struct UnkStruct_800DC5EC*, s32); s32 func_80290C20(Camera*); -void parse_course_displaylists(const char* asset); +void parse_course_displaylists(TrackSectionsI* asset); void render_course_segments(const char*[], struct UnkStruct_800DC5EC*); void func_80291198(void); void func_802911C4(void); diff --git a/src/render_objects.c b/src/render_objects.c index 71c31fddc..d32d08046 100644 --- a/src/render_objects.c +++ b/src/render_objects.c @@ -42,6 +42,9 @@ #include #include "port/Game.h" +#include "engine/Engine.h" +#include "engine/courses/Course.h" + Lights1 D_800E45C0[] = { gdSPDefLights1(100, 0, 0, 100, 0, 0, 0, -120, 0), gdSPDefLights1(100, 100, 0, 255, 255, 0, 0, -120, 0), @@ -2472,8 +2475,8 @@ void func_8004EF9C(s32 arg0) { s16 temp_t0; s16 temp_v0; - temp_v0 = D_800E5548[arg0 * 2]; - temp_t0 = D_800E5548[arg0 * 2 + 1]; + temp_v0 = CourseManager_GetProps()->D_800E5548[0]; // D_800E5548[arg0 * 2]; + temp_t0 = CourseManager_GetProps()->D_800E5548[1]; // D_800E5548[arg0 * 2 + 1]; func_8004D37C(0x00000104, 0x0000003C, D_8018D248[arg0], 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF, temp_v0, temp_t0, temp_v0, temp_t0); } @@ -3854,7 +3857,7 @@ void render_object_trains_smoke_particles(s32 cameraId) { // Render smoke for any number of trains. Don't know enough about these variables yet. #ifdef AVOID_UB_WIP - for (j = 0; j < gNumTrains; j++) { + for (j = 0; j < NUM_TRAINS; j++) { if ((gTrainList[j].someFlags != 0) && (is_particle_on_screen(&gTrainList[j].locomotive.position, camera, 0x4000U) != 0)) { diff --git a/src/spawn_players.c b/src/spawn_players.c index 6e015ff3b..c4d792637 100644 --- a/src/spawn_players.c +++ b/src/spawn_players.c @@ -552,10 +552,10 @@ void spawn_players_gp_one_player(f32* arg0, f32* arg1, f32 arg2) { if (gNetwork.enabled) { spawn_network_players(arg0, arg1, arg2); } else { - spawn_player(gPlayerTwo, 1, arg0[0], arg1[0] + 250.0f, arg2, 32768.0f, chooseKartAIPlayers[0], - PLAYER_EXISTS | PLAYER_STAGING | PLAYER_START_SEQUENCE | PLAYER_KART_AI); - spawn_player(gPlayerOneCopy, 0, arg0[1], arg1[1] + 250.0f, arg2, 32768.0f, gCharacterSelections[0], + spawn_player(gPlayerOneCopy, 0, arg0[D_80165270[0]], arg1[D_80165270[0]] + 250.0f, arg2, 32768.0f, gCharacterSelections[0], PLAYER_EXISTS | PLAYER_STAGING | PLAYER_START_SEQUENCE | PLAYER_HUMAN); + spawn_player(gPlayerTwo, 1, arg0[D_80165270[1]], arg1[D_80165270[1]] + 250.0f, arg2, 32768.0f, chooseKartAIPlayers[0], + PLAYER_EXISTS | PLAYER_STAGING | PLAYER_START_SEQUENCE | PLAYER_KART_AI); spawn_player(gPlayerThree, 2, arg0[D_80165270[3]], arg1[D_80165270[2]] + 250.0f, arg2, 32768.0f, chooseKartAIPlayers[1], PLAYER_EXISTS | PLAYER_STAGING | PLAYER_START_SEQUENCE | PLAYER_KART_AI);