Files
SpaghettiKart/src/engine/courses/KoopaTroopaBeach.cpp
T

350 lines
13 KiB
C++

#include <libultraship.h>
#include <libultra/gbi.h>
#include <vector>
#include <memory>
#include "KoopaTroopaBeach.h"
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/objects/OBombKart.h"
#include "assets/koopa_troopa_beach_data.h"
extern "C" {
#include "main.h"
#include "camera.h"
#include "course_offsets.h"
#include "code_800029B0.h"
#include "render_courses.h"
#include "code_8006E9C0.h"
#include "code_80057C60.h"
#include "defines.h"
#include "math_util.h"
#include "external.h"
#include "code_80005FD0.h"
#include "spawn_players.h"
#include "render_objects.h"
#include "assets/common_data.h"
#include "save.h"
#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;
}
const course_texture koopa_troopa_beach_textures[] = {
{ gTexture643B3C, 0x0798, 0x0800, 0x0 },
{ gTexture66A3DC, 0x07C5, 0x0800, 0x0 },
{ gTextureSignWoodRedArrow, 0x04E1, 0x1000, 0x0 },
{ gTexture66DD38, 0x0330, 0x1000, 0x0 },
{ gTexture643430, 0x0604, 0x0800, 0x0 },
{ gTexture660D8C, 0x0126, 0x0800, 0x0 },
{ gTexture6609D0, 0x03BB, 0x1000, 0x0 },
{ gTextureGrass12, 0x0874, 0x0800, 0x0 },
{ gTexture66CA98, 0x02C9, 0x0800, 0x0 },
{ gTexture66EBF0, 0x0146, 0x0800, 0x0 },
{ gTexture67BEE8, 0x02D0, 0x0800, 0x0 },
{ gTextureSandFinish, 0x022E, 0x0800, 0x0 },
{ gTextureWheelSteamEngine, 0x020F, 0x0800, 0x0 },
{ gTexture669570, 0x0E6B, 0x1000, 0x0 },
{ gTextureWaves1, 0x05C4, 0x0800, 0x0 },
{ gTextureWaves2, 0x0488, 0x0800, 0x0 },
{ 0x00000000, 0x0000, 0x0000, 0x0 },
};
KoopaTroopaBeach::KoopaTroopaBeach() {
this->vtx = d_course_koopa_troopa_beach_vertex;
this->gfx = d_course_koopa_troopa_beach_packed_dls;
this->gfxSize = 5720;
Props.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";
Props.DebugName = "beach";
Props.CourseLength = "691m";
Props.AIBehaviour = D_0D009158;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.5f;
Props.SomePtr = D_800DCAF4;
Props.AISteeringSensitivity = 53;
Props.NearPersp = 1.0f;
Props.FarPersp = 5000.0f;
Props.PathSizes = {0x2BC, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0};
Props.D_0D009418[0] = 4.1666665f;
Props.D_0D009418[1] = 5.5833334f;
Props.D_0D009418[2] = 6.1666665f;
Props.D_0D009418[3] = 6.75f;
Props.D_0D009568[0] = 3.75f;
Props.D_0D009568[1] = 5.1666665f;
Props.D_0D009568[2] = 5.75f;
Props.D_0D009568[3] = 6.3333334f;
Props.D_0D0096B8[0] = 3.3333332f;
Props.D_0D0096B8[1] = 3.9166667f;
Props.D_0D0096B8[2] = 4.5f;
Props.D_0D0096B8[3] = 5.0833334f;
Props.D_0D009808[0] = 3.75f;
Props.D_0D009808[1] = 5.1666665f;
Props.D_0D009808[2] = 5.75f;
Props.D_0D009808[3] = 6.3333334f;
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] = (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;
Props.Clouds = gKoopaTroopaBeachClouds;
Props.CloudList = gKoopaTroopaBeachClouds;
Props.MinimapFinishlineX = 0;
Props.MinimapFinishlineY = 0;
Props.Skybox.TopRight = {48, 152, 120};
Props.Skybox.BottomRight = {216, 232, 248};
Props.Skybox.BottomLeft = {216, 232, 248};
Props.Skybox.TopLeft = {48, 152, 120};
Props.Skybox.FloorTopRight = {48, 152, 120};
Props.Skybox.FloorBottomRight = {0, 0, 0};
Props.Skybox.FloorBottomLeft = {0, 0, 0};
Props.Skybox.FloorTopLeft = {48, 152, 120};
Props.Sequence = MusicSeq::MUSIC_SEQ_KOOPA_TROOPA_BEACH;
}
void KoopaTroopaBeach::Load() {
Course::Load();
parse_course_displaylists((TrackSectionsI*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_addr));
func_80295C6C();
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x0700ADE0), -0x6A, 255, 255, 255);
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x0700A540), -0x6A, 255, 255, 255);
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07009E70), -0x6A, 255, 255, 255);
find_vtx_and_set_colours(segmented_gfx_to_virtual((void*)0x07000358), -0x6A, 255, 255, 255);
}
void KoopaTroopaBeach::LoadTextures() {
}
void KoopaTroopaBeach::SpawnActors() {
gWorldInstance.AddActor(new AFinishline());
init_actor_hot_air_balloon_item_box(328.0f * gCourseDirection, 70.0f, 2541.0f);
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::SpawnVehicles() {
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
gWorldInstance.AddBombKart(pos, &D_80164550[0][60], 60, 1, 0.8333333f);
gWorldInstance.AddBombKart(pos, &D_80164550[0][120], 120, 1, 0.8333333f);
gWorldInstance.AddBombKart(pos, &D_80164550[0][200], 200, 3, 0.8333333f);
gWorldInstance.AddBombKart(pos, &D_80164550[0][280], 280, 1, 0.8333333f);
gWorldInstance.AddBombKart(pos, &D_80164550[0][435], 435, 3, 0.8333333f);
gWorldInstance.AddBombKart(pos, &D_80164550[0][0], 0, 0, 0.8333333f);
gWorldInstance.AddBombKart(pos, &D_80164550[0][0], 0, 0, 0.8333333f);
}
}
// Likely sets minimap boundaries
void KoopaTroopaBeach::MinimapSettings() {
D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust3, 0x3C8U, 0x1000));
D_8018D2A0 = 0.014f;
D_8018D2C0[0] = 268;
D_8018D2E0 = 40;
D_8018D2E8 = 21;
}
void KoopaTroopaBeach::InitCourseObjects() {
size_t objectId;
size_t i;
if (gGamestate != CREDITS_SEQUENCE) {
for (i = 0; i < NUM_CRABS; i++) {
objectId = indexObjectList1[i];
init_object(objectId, 0);
gObjectList[objectId].pos[0] = gObjectList[objectId].origin_pos[0] =
gCrabSpawns[i].startX * xOrientation;
gObjectList[objectId].unk_01C[0] = gCrabSpawns[i].patrolX * xOrientation;
gObjectList[objectId].pos[2] = gObjectList[objectId].origin_pos[2] = gCrabSpawns[i].startZ;
gObjectList[objectId].unk_01C[2] = gCrabSpawns[i].patrolZ;
}
}
for (i = 0; i < NUM_SEAGULLS; i++) {
objectId = indexObjectList2[i];
init_object(objectId, 0);
if (i < (NUM_SEAGULLS / 2)) {
gObjectList[objectId].unk_0D5 = 0;
} else {
gObjectList[objectId].unk_0D5 = 1;
}
}
}
void KoopaTroopaBeach::UpdateCourseObjects() {
if (gGamestate != CREDITS_SEQUENCE) {
update_crabs();
}
if ((gPlayerCount == 1) || (gPlayerCount == 2) || (gGamestate == CREDITS_SEQUENCE)) {
update_seagulls();
}
}
void KoopaTroopaBeach::RenderCourseObjects(s32 cameraId) {
if (gGamestate != CREDITS_SEQUENCE) {
render_object_crabs(cameraId);
}
if (gGamestate != CREDITS_SEQUENCE) {
if ((gPlayerCount == 1) || (gPlayerCount == 2)) {
render_object_seagulls(cameraId);
}
} else {
render_object_seagulls(cameraId);
}
}
void KoopaTroopaBeach::SomeSounds() {
vec3f_set(D_8015F738, 153.0f, 0.0f, 2319.0f);
func_800C9D80(D_8015F738, D_802B91C8, 0x51028001);
}
void KoopaTroopaBeach::WhatDoesThisDo(Player* player, int8_t playerId) {}
void KoopaTroopaBeach::WhatDoesThisDoAI(Player* player, int8_t playerId) {}
// Positions the finishline on the minimap
void KoopaTroopaBeach::MinimapFinishlinePosition() {
//! todo: Place hard-coded values here.
draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, (u8*) common_texture_minimap_finish_line);
}
void KoopaTroopaBeach::Render(struct UnkStruct_800DC5EC* arg0) {
gDPPipeSync(gDisplayListHead++);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH);
if (func_80290C20(arg0->camera) == 1) {
gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
// d_course_koopa_troopa_beach_packed_dl_9CC0
gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07009CC0)));
}
gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
// d_course_koopa_troopa_beach_packed_dl_9688
gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07009688)));
render_course_segments((const char**)d_course_koopa_troopa_beach_dl_list1, arg0);
gSPClearGeometryMode(gDisplayListHead++, G_CULL_BACK);
gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_TEX_EDGE, G_RM_AA_ZB_TEX_EDGE2);
// d_course_koopa_troopa_beach_packed_dl_2C0
gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual(reinterpret_cast<void*>(0x070002C0)));
gSPSetGeometryMode(gDisplayListHead++, G_CULL_BACK);
gDPPipeSync(gDisplayListHead++);
}
void KoopaTroopaBeach::RenderCredits() {
gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_koopa_troopa_beach_dl_18D68));
}
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::ScrollingTextures() {
// clang-format off
if (D_8015F8E8 < 0.0f) {
if (D_8015F8E4 < -20.0f) { D_8015F8E8 *= -1.0f; }
} else {
if (D_8015F8E4 > 0.0f) { D_8015F8E8 *= -1.0f; }
}
// clang-format on
D_8015F8E4 += D_8015F8E8;
D_802B87BC += 9;
if (D_802B87BC > 255) {
D_802B87BC = 0;
}
D_802B87C4 += 3;
if (D_802B87C4 > 255) {
D_802B87C4 = 0;
}
// waterfall animation
// d_course_koopa_troopa_beach_packed_dl_9D58
find_and_set_tile_size((uintptr_t)segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07009D58)), 0, D_802B87BC);
// d_course_koopa_troopa_beach_packed_dl_9CD0
find_and_set_tile_size((uintptr_t)segmented_gfx_to_virtual(reinterpret_cast<void*>(0x07009CD0)), 0, D_802B87C4);
D_802B87CC = random_int(300) / 40;
if (D_802B87C8 < 0) {
D_802B87C8 = random_int(300) / 40;
} else {
D_802B87C8 = -(random_int(300) / 40);
}
// Waterfall bubbling effect? (unused)
// d_course_koopa_troopa_beach_packed_dl_2E8
find_and_set_tile_size((uintptr_t)segmented_gfx_to_virtual(reinterpret_cast<void*>(0x070002E8)), D_802B87C8, D_802B87CC);
}
void KoopaTroopaBeach::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) {
Mat4 matrix;
Vec3f vector;
gDPPipeSync(gDisplayListHead++);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_XLU_INTER, G_RM_NOOP2);
gDPSetBlendMask(gDisplayListHead++, 0xFF);
gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
switch (pathCounter) {
case 22:
case 23:
case 29:
case 30:
case 31:
case 37:
gSPClearGeometryMode(gDisplayListHead++, G_CULL_BACK);
// d_course_koopa_troopa_beach_packed_dl_9E70
gSPDisplayList(gDisplayListHead++, segmented_gfx_to_virtual((void*)0x07009E70));
gSPSetGeometryMode(gDisplayListHead++, G_CULL_BACK);
break;
}
vector[0] = 0.0f;
vector[1] = D_8015F8E4;
vector[2] = 0.0f;
mtxf_translate(matrix, vector);
render_set_position(matrix, 0);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_XLU_INTER, G_RM_NOOP2);
gDPSetBlendMask(gDisplayListHead++, 0xFF);
gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
gSPClearGeometryMode(gDisplayListHead++, G_CULL_BACK);
render_course_segments((const char**)koopa_troopa_beach_dls2, screen);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 1, 1, G_OFF);
gSPSetGeometryMode(gDisplayListHead++, G_CULL_BACK);
gDPSetAlphaCompare(gDisplayListHead++, G_AC_NONE);
gDPPipeSync(gDisplayListHead++);
}
void KoopaTroopaBeach::Destroy() {}