Fix podium ceremony. Wip particle emitters

This commit is contained in:
MegaMech
2024-12-28 20:30:18 -07:00
parent 8309225412
commit 9c4b35206a
26 changed files with 407 additions and 325 deletions
+16 -13
View File
@@ -551,22 +551,21 @@ void render_object(u32 arg0) {
}
void render_object_p1(void) {
gDPSetTexturePersp(gDisplayListHead++, G_TP_PERSP);
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxPersp[0]),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxLookAt[0]),
G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
CourseManager_DrawBombKarts(PLAYER_ONE);
//render_bomb_karts_wrap(PLAYER_ONE);
if (gGamestate == ENDING) {
//func_80055F48(PLAYER_ONE);
//func_80056160(PLAYER_ONE);
//func_8005217C(PLAYER_ONE);
//func_80054BE8(PLAYER_ONE);
return;
}
CourseManager_DrawBombKarts(PLAYER_ONE); // render_bomb_karts_wrap(PLAYER_ONE);
// if (gGamestate == ENDING) {
// //func_80055F48(PLAYER_ONE);
// //func_80056160(PLAYER_ONE);
// //func_8005217C(PLAYER_ONE);
// //func_80054BE8(PLAYER_ONE);
// return;
// }
render_object_for_player(PLAYER_ONE);
}
@@ -690,8 +689,8 @@ void render_player_snow_effect_four(void) {
}
void render_object_for_player(s32 cameraId) {
CourseManager_DrawObjects(cameraId);
CM_DrawParticles(cameraId);
// CourseManager_RenderCourseObjects(cameraId);
// CourseManager_TrainSmokeDraw(cameraId);
@@ -1408,6 +1407,7 @@ void func_80059D00(void) {
}
update_object();
CourseManager_TickObjects();
CM_TickParticles();
func_800744CC();
}
}
@@ -1423,12 +1423,15 @@ void func_8005A070(void) {
//func_80086604();
//func_80086D80();
//update_cheep_cheep(1);
func_80077640();
//func_80077640();
CourseManager_TickObjects();
CM_TickParticles();
} else if (gGamestate == CREDITS_SEQUENCE) {
func_80059820(PLAYER_ONE);
func_80078C70(0);
CourseManager_TickObjects();
} else {
CM_TickParticles();
} else { // normal gameplay
func_80059D00();
}
}
+2 -1
View File
@@ -89,7 +89,7 @@ void func_802818BC(void) {
}
}
void load_ceremony_cutscene(void) {
void setup_podium_ceremony(void) {
Camera* camera = &cameras[0];
gCurrentCourseId = COURSE_ROYAL_RACEWAY;
@@ -164,6 +164,7 @@ void load_ceremony_cutscene(void) {
balloons_and_fireworks_init();
init_camera_podium_ceremony();
func_80093E60();
CourseManager_SpawnActors();
D_801625F8 = (uintptr_t) gHeapEndPtr - gNextFreeMemoryAddress;
D_801625FC = ((f32) D_801625F8 / 1000.0f);
}
+1 -1
View File
@@ -6,7 +6,7 @@
void debug_switch_character_ceremony_cutscene(void);
s32 func_80281880(s32 arg0);
void func_802818BC(void);
void load_ceremony_cutscene(void);
void setup_podium_ceremony(void);
extern s32 D_80287554;
extern f32 D_801647A4;
+1 -1
View File
@@ -131,7 +131,7 @@ void func_80281D00(void) {
render_players_on_screen_one();
gSPDisplayList(gDisplayListHead++, VIRTUAL_TO_PHYSICAL2(&D_80284EE0));
update_actors_loop();
render_object(PLAYER_ONE + SCREEN_MODE_1P);
render_object(RENDER_SCREEN_MODE_1P_PLAYER_ONE);
func_80021B0C();
gSPDisplayList(gDisplayListHead++, VIRTUAL_TO_PHYSICAL2(&D_80284EE0));
func_80093F10();
+16
View File
@@ -254,6 +254,10 @@ void World::TickObjects60fps() {
}
}
ParticleEmitter* World::AddEmitter(ParticleEmitter* emitter) {
Emitters.push_back(emitter);
return Emitters.back();
}
void World::DrawObjects(s32 cameraId) {
for (const auto& object : Objects) {
@@ -261,6 +265,18 @@ void World::DrawObjects(s32 cameraId) {
}
}
void World::TickParticles() {
for (const auto& emitter : Emitters) {
emitter->Tick();
}
}
void World::DrawParticles(s32 cameraId) {
for (const auto& emitter : Emitters) {
emitter->Draw(cameraId);
}
}
Object* World::GetObjectByIndex(size_t index) {
//if (index < this->Objects.size()) {
// Assuming GameActor::a is accessible, use reinterpret_cast if needed
+4
View File
@@ -164,6 +164,10 @@ public:
void DrawObjects(s32 cameraId);
Object *GetObjectByIndex(size_t);
void TickParticles();
void DrawParticles(s32 cameraId);
ParticleEmitter* AddEmitter(ParticleEmitter* emitter);
void AddCup(Cup*);
void SetCup(Cup* cup);
const char* GetCupName();
+4 -4
View File
@@ -165,11 +165,11 @@ void PodiumCeremony::SpawnActors() {
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));
gWorldInstance.AddObject(new OCheepCheep(FVector((f32)0xf37e, (f32)0x0013, (f32)0xfe22), OCheepCheep::CheepType::PODIUM_CEREMONY, IPathSpan(0, 0)));
gWorldInstance.AddObject(new OPodium(FVector((f32)0xf37e, (f32)0x0013, (f32)0xfe22)));
gWorldInstance.AddObject(new OCheepCheep(FVector((f32)-3202, (f32)19, (f32)-478), OCheepCheep::CheepType::PODIUM_CEREMONY, IPathSpan(0, 0)));
gWorldInstance.AddObject(new OPodium(FVector((f32)-3202, (f32)19, (f32)-478)));
FVector pos = {0,0,0};
pos.y = 90.0f;
FVector pos = {0, 90.0f, 0};
OTrophy::TrophyType type = OTrophy::TrophyType::BRONZE;
switch(D_802874D8.unk1D) {
case 0: // Bronze
-1
View File
@@ -52,7 +52,6 @@ void OCheepCheep::Draw(s32 cameraId) { // func_8005217C
Lights1* D_800E45C0l = (Lights1*) (D_800E45C0);
Object* object;
s32 temp_a3;
temp_a3 = indexObjectList2[0];
object = &gObjectList[temp_a3];
if (object->state >= 2) {
+3 -1
View File
@@ -11,14 +11,16 @@ class OObject {
public:
uint8_t uuid[16];
Object o;
bool PendingDestroy = false;
virtual ~OObject() = default;
explicit OObject();
virtual void Tick();
virtual void Tick60fps();
virtual void Draw(s32 cameraId);
virtual void Collision();
virtual void Expire();
virtual void Destroy();
virtual void Destroy(); // Mark object for deletion at the start of the next frame
};
+16 -14
View File
@@ -27,24 +27,26 @@ extern Vec3s D_800E634C[];
OPodium::OPodium(const FVector& pos) {
_pos = pos;
for (size_t i = 0; i < NUM_PODIUMS; i++) {
s32 objectIndex = indexObjectList1[i];
init_object(objectIndex, 0);
set_obj_origin_pos(objectIndex, pos.x - 1.5, pos.y, pos.z);
//init_object(objectIndex, 0);
//set_obj_origin_pos(objectIndex, pos.x - 1.5, pos.y, pos.z);
}
}
void OPodium::Tick() { // func_80086604
s32 objectIndex;
// if ((D_8016347C != 0) && (D_802874D8.unk1D < 3)) {
// if (D_801658C6 == 0) {
// for (size_t i = 0; i < 3; i++) {
// objectIndex = indexObjectList1[i];
// init_object(objectIndex, 0);
// }
// D_801658C6 = 1;
// }
// }
if ((D_8016347C != 0) && (D_802874D8.unk1D < 3)) {
if (D_801658C6 == 0) {
for (size_t i = 0; i < 3; i++) {
objectIndex = indexObjectList1[i];
init_object(objectIndex, 0);
}
D_801658C6 = 1;
}
}
for (size_t i = 0; i != NUM_PODIUMS; i++) {
objectIndex = indexObjectList1[i];
if (gObjectList[objectIndex].state != 0) {
@@ -58,9 +60,9 @@ void OPodium::Draw(s32 cameraId) { // func_80055F48
for (size_t i = 0; i < NUM_PODIUMS; i++) {
Object* object;
object = &gObjectList[i];
object = &gObjectList[indexObjectList1[i]];
if (object->state >= 2) {
func_80043220(object->pos, object->direction_angle, object->sizeScaling, object->model);
//func_80043220(object->pos, object->direction_angle, object->sizeScaling, object->model);
rsp_set_matrix_transformation(object->pos, object->direction_angle, object->sizeScaling);
gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D0077A0);
gSPDisplayList(gDisplayListHead++, object->model);
@@ -86,7 +88,7 @@ void OPodium::func_8008629C(s32 objectIndex, s32 arg1) {
break;
}
gObjectList[objectIndex].sizeScaling = 1.0f;
//set_obj_origin_pos(objectIndex, D_800E634C[0][0] - 1.5, D_800E634C[0][1], D_800E634C[0][2]);
set_obj_origin_pos(objectIndex, _pos.x - 1.5, _pos.y, _pos.z);
set_obj_origin_offset(objectIndex, 0.0f, -10.0f, 0.0f);
set_obj_direction_angle(objectIndex, 0U, 0xF8E4U, 0U);
gObjectList[objectIndex].unk_048 = 0;
+1
View File
@@ -35,4 +35,5 @@ public:
private:
s32 _idx;
FVector _pos;
};
+76 -16
View File
@@ -24,7 +24,18 @@ OTrophy::OTrophy(const FVector& pos, TrophyType trophy, Behaviour bhv) {
_spawnPos.y += 16.0f; // Adjust the height so the trophy sits on the surface when positioned to 0,0,0
_bhv = bhv;
init_object(objectIndex, 0);
if (bhv == OTrophy::Behaviour::PODIUM_CEREMONY) {
_toggleVisibility = &D_801658CE;
} else {
int8_t toggle = 1;
_toggleVisibility = &toggle;
_isMod = true;
}
// This allows spawning for mods
if (*_toggleVisibility == true) {
init_object(objectIndex, 0);
}
switch (trophy) {
case TrophyType::GOLD:
@@ -47,13 +58,6 @@ OTrophy::OTrophy(const FVector& pos, TrophyType trophy, Behaviour bhv) {
break;
}
if (OTrophy::Behaviour::PODIUM_CEREMONY) {
_toggleVisibility = &D_801658CE;
} else {
int8_t toggle = 1;
_toggleVisibility = &toggle;
}
// Set defaults for modded behaviours
if (_bhv != OTrophy::Behaviour::PODIUM_CEREMONY) {
gObjectList[objectIndex].sizeScaling = 0.025f;
@@ -81,15 +85,15 @@ void OTrophy::Tick() { // func_80086D80
s32 objectIndex = indexObjectList1[3];
s32 var_s0;
// if ((D_801658CE != 0) && (D_801658DC == 0)) {
// temp_s2 = indexObjectList1[3];
// init_object(temp_s2, 0);
// D_801658DC = 1;
// }
// Fallback for podium ceremony where the trophy is not spawned until it is needed
if ((*_toggleVisibility == true) && (D_801658DC == 0) && (_isMod == false)) {
init_object(objectIndex, 0);
D_801658DC = 1;
}
switch(_bhv) {
case OTrophy::Behaviour::PODIUM_CEREMONY:
if (gObjectList[objectIndex].state != 0) {
if (gObjectList[objectIndex].state != 0 && (*_toggleVisibility == true)) {
OTrophy::func_80086C14(objectIndex);
OTrophy::func_80086940(objectIndex);
if (D_801658F4 != 0) {
@@ -197,8 +201,7 @@ void OTrophy::Draw(s32 cameraId) {
Mat4 someMatrix1;
Mat4 someMatrix2;
Object* object;
if (_toggleVisibility) {
if (*_toggleVisibility == true) {
object = &gObjectList[listIndex];
if (object->state >= 2) {
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxPersp[0]),
@@ -332,3 +335,60 @@ void OTrophy::func_80086C6C(s32 objectIndex) {
}
func_800773D8(sp24, (s32) D_801658F4);
}
void OTrophy::func_800773D8(f32* arg0, s32 arg1) {
s32 objectIndex = add_unused_obj_index(gObjectParticle3, &gNextFreeObjectParticle3, gObjectParticle3_SIZE);
if (objectIndex != NULL_OBJECT_ID) {
func_80077138(objectIndex, arg0, arg1);
}
}
void OTrophy::func_80077138(s32 objectIndex, Vec3f arg1, s32 arg2) {
s8 temp_v0_3;
Vec3s sp30;
init_object(objectIndex, arg2);
gObjectList[objectIndex].unk_0D5 = 0x0C;
gObjectList[objectIndex].sizeScaling = 0.05f;
set_obj_origin_pos(objectIndex, arg1[0], arg1[1], arg1[2]);
set_obj_orientation(objectIndex, 0U, 0U, 0U);
set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f);
switch (arg2) {
case 0:
gObjectList[objectIndex].velocity[1] = -1.0f;
gObjectList[objectIndex].unk_034 = (f32) ((random_int(0x004BU) * 0.01) + 0.25);
gObjectList[objectIndex].direction_angle[1] = random_int(0x0040U) << 0xA;
func_8008751C(objectIndex);
gObjectList[objectIndex].unk_084[5] = 0x001E;
break;
case 1:
gObjectList[objectIndex].velocity[1] = 1.5f;
gObjectList[objectIndex].unk_034 = (f32) ((random_int(0x0064U) * 0.01) + 0.5);
gObjectList[objectIndex].direction_angle[1] = random_int(0x0040U) << 0xA;
func_8008751C(objectIndex);
gObjectList[objectIndex].unk_084[5] = 0x0032;
break;
}
temp_v0_3 = random_int(0x000CU);
if (temp_v0_3 < 9) {
func_8005C674(temp_v0_3, &sp30[2], &sp30[1], sp30);
gObjectList[objectIndex].unk_048 = 0;
gObjectList[objectIndex].unk_084[0] = sp30[2];
gObjectList[objectIndex].unk_084[1] = sp30[1];
gObjectList[objectIndex].unk_084[2] = sp30[0];
} else {
temp_v0_3 = random_int(3U);
func_8005C6B4(temp_v0_3, &sp30[2], &sp30[1], sp30);
gObjectList[objectIndex].unk_084[0] = sp30[2];
gObjectList[objectIndex].unk_084[1] = sp30[1];
gObjectList[objectIndex].unk_084[2] = sp30[0];
gObjectList[objectIndex].unk_084[4] = temp_v0_3;
gObjectList[objectIndex].unk_048 = 1;
}
gObjectList[objectIndex].primAlpha = 0x00FF;
gObjectList[objectIndex].unk_084[3] = random_int(0x0800U) + 0x400;
if ((gObjectList[objectIndex].direction_angle[1] < 0x3000) ||
(gObjectList[objectIndex].direction_angle[1] >= 0xB001)) {
gObjectList[objectIndex].unk_084[3] = -gObjectList[objectIndex].unk_084[3];
}
}
+3
View File
@@ -43,6 +43,8 @@ public:
void func_80086940(s32 objectIndex);
void func_80086C14(s32 objectIndex);
void func_80086C6C(s32 objectIndex);
void func_800773D8(f32* arg0, s32 arg1);
void func_80077138(s32 objectIndex, Vec3f arg1, s32 arg2);
private:
@@ -52,4 +54,5 @@ private:
Behaviour _bhv;
int8_t *_toggleVisibility;
Vec3f _oldPos;
bool _isMod = false;
};
+150 -2
View File
@@ -6,10 +6,89 @@ extern "C" {
#include "render_objects.h"
#include "common_data.h"
#include "code_80057C60.h"
#include "update_objects.h"
#include "code_80086E70.h"
#include "math_util.h"
#include "math_util_2.h"
}
void StarEmitter::Tick() {
StarEmitter::StarEmitter(FVector pos) {
s32 objectIndex = add_unused_obj_index(gObjectParticle3, &gNextFreeObjectParticle3, gObjectParticle3_SIZE);
s8 temp_v0_3;
Vec3s sp30;
if (objectIndex == NULL_OBJECT_ID) {
return;
//func_80077138(objectIndex, arg0, arg1);
}
D_801658F4 = 1;
init_object(objectIndex, D_801658F4);
gObjectList[objectIndex].unk_0D5 = 0x0C;
gObjectList[objectIndex].sizeScaling = 0.05f;
set_obj_origin_pos(objectIndex, pos.x, pos.y, pos.z);
set_obj_orientation(objectIndex, 0U, 0U, 0U);
set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f);
switch (D_801658F4) {
case 0:
gObjectList[objectIndex].velocity[1] = -1.0f;
gObjectList[objectIndex].unk_034 = (f32) ((random_int(0x004BU) * 0.01) + 0.25);
gObjectList[objectIndex].direction_angle[1] = random_int(0x0040U) << 0xA;
func_8008751C(objectIndex);
gObjectList[objectIndex].unk_084[5] = 0x001E;
break;
case 1:
gObjectList[objectIndex].velocity[1] = 1.5f;
gObjectList[objectIndex].unk_034 = (f32) ((random_int(0x0064U) * 0.01) + 0.5);
gObjectList[objectIndex].direction_angle[1] = random_int(0x0040U) << 0xA;
func_8008751C(objectIndex);
gObjectList[objectIndex].unk_084[5] = 0x0032;
break;
}
temp_v0_3 = random_int(0x000CU);
if (temp_v0_3 < 9) {
func_8005C674(temp_v0_3, &sp30[2], &sp30[1], sp30);
gObjectList[objectIndex].unk_048 = 0;
gObjectList[objectIndex].unk_084[0] = sp30[2];
gObjectList[objectIndex].unk_084[1] = sp30[1];
gObjectList[objectIndex].unk_084[2] = sp30[0];
} else {
temp_v0_3 = random_int(3U);
func_8005C6B4(temp_v0_3, &sp30[2], &sp30[1], sp30);
gObjectList[objectIndex].unk_084[0] = sp30[2];
gObjectList[objectIndex].unk_084[1] = sp30[1];
gObjectList[objectIndex].unk_084[2] = sp30[0];
gObjectList[objectIndex].unk_084[4] = temp_v0_3;
gObjectList[objectIndex].unk_048 = 1;
}
gObjectList[objectIndex].primAlpha = 0x00FF;
gObjectList[objectIndex].unk_084[3] = random_int(0x0800U) + 0x400;
if ((gObjectList[objectIndex].direction_angle[1] < 0x3000) ||
(gObjectList[objectIndex].direction_angle[1] >= 0xB001)) {
gObjectList[objectIndex].unk_084[3] = -gObjectList[objectIndex].unk_084[3];
}
}
void StarEmitter::Tick() { // func_80077640
s32 someIndex;
s32 objectIndex;
Object* object;
for (someIndex = 0; someIndex < gObjectParticle3_SIZE; someIndex++) {
objectIndex = gObjectParticle3[someIndex];
if (objectIndex != DELETED_OBJECT_ID) {
object = &gObjectList[objectIndex];
printf("Tick Star %d\n", object->state);
if (object->state != 0) {
StarEmitter::func_80077450(objectIndex);
StarEmitter::func_80077584(objectIndex);
if (object->state == 0) {
delete_object_wrapper(&gObjectParticle3[someIndex]);
}
}
}
}
}
void StarEmitter::Draw(s32 cameraId) { // func_80054BE8
@@ -22,10 +101,79 @@ void StarEmitter::Draw(s32 cameraId) { // func_80054BE8
load_texture_block_ia8_nomirror(D_8018D488, 0x00000020, 0x00000020);
func_8004B35C(0x000000FF, 0x000000FF, 0, 0x000000FF);
D_80183E80[0] = 0;
printf("Draw Star\n");
for (var_s0 = 0; var_s0 < gObjectParticle3_SIZE; var_s0++) {
temp_a0 = gObjectParticle3[var_s0];
if ((temp_a0 != -1) && (gObjectList[temp_a0].state >= 2)) {
func_80054AFC(temp_a0, camera->pos);
StarEmitter::func_80054AFC(temp_a0, camera->pos);
}
}
}
void StarEmitter::func_80054AFC(s32 objectIndex, Vec3f arg1) {
printf("Drawing Star!\n");
D_80183E80[0] = func_800418E8(gObjectList[objectIndex].pos[2], gObjectList[objectIndex].pos[1], arg1);
D_80183E80[1] = func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], arg1);
D_80183E80[2] = (u16) gObjectList[objectIndex].orientation[2];
func_8004B138((s32) gObjectList[objectIndex].unk_084[0], (s32) gObjectList[objectIndex].unk_084[1],
(s32) gObjectList[objectIndex].unk_084[2], (s32) gObjectList[objectIndex].primAlpha);
rsp_set_matrix_transformation(gObjectList[objectIndex].pos, (u16*) D_80183E80,
gObjectList[objectIndex].sizeScaling);
gSPVertex(gDisplayListHead++, (uintptr_t)D_0D005AE0, 4, 0);
gSPDisplayList(gDisplayListHead++, (Gfx*)common_rectangle_display);
}
void StarEmitter::func_80077428(s32 objectIndex) {
object_next_state(objectIndex);
func_80086E70(objectIndex);
}
void StarEmitter::func_80077584(s32 objectIndex) {
Object* object;
object = &gObjectList[objectIndex];
if ((object->unk_0AE != 0) && (object->unk_0AE == 1) && ((u8) object->unk_0D8 != 0)) {
if (object->velocity[1] >= -0.5) {
object->velocity[1] -= 0.15;
} else {
object->velocity[2] = 0.0f;
object->velocity[0] = 0.0f;
}
}
object->orientation[2] += object->unk_084[3];
object_add_velocity_offset_xyz(objectIndex);
object_calculate_new_pos_offset(objectIndex);
}
void StarEmitter::func_80077450(s32 objectIndex) {
UNUSED s16 stackPadding0;
s16 sp3C;
s16 sp3A;
s16 sp38;
switch (gObjectList[objectIndex].state) {
case 0:
break;
case 1:
StarEmitter::func_80077428(objectIndex);
break;
case 2:
f32_step_up_towards(&gObjectList[objectIndex].sizeScaling, 0.1f, 0.01f);
if ((gObjectList[objectIndex].pos[1] <= gObjectList[objectIndex].unk_084[5]) &&
(func_80073B00(objectIndex, &gObjectList[objectIndex].primAlpha, 0x000000FF, 0, 0x00000010, 0, 0) !=
0)) {
func_80086F60(objectIndex);
func_80072428(objectIndex);
}
break;
}
if (gObjectList[objectIndex].unk_048 != 0) {
printf("SOME THING\n");
gObjectList[objectIndex].unk_084[4] = (s16) ((s32) (gObjectList[objectIndex].unk_084[4] + 1) % 3);
func_8005C6B4(gObjectList[objectIndex].unk_084[4], &sp3C, &sp3A, &sp38);
gObjectList[objectIndex].unk_084[0] = sp3C;
gObjectList[objectIndex].unk_084[1] = sp3A;
gObjectList[objectIndex].unk_084[2] = sp38;
}
}
+6 -5
View File
@@ -3,6 +3,7 @@
#include <libultraship.h>
#include <vector>
#include "ParticleEmitter.h"
#include "World.h"
extern "C" {
#include "macros.h"
@@ -27,14 +28,14 @@ public:
f32 Diameter = 0.0f; // Waddle in a circle around the spawn point at this diameter.
uint16_t MirrorModeAngleOffset;
explicit StarEmitter(Vec3f pos);
explicit StarEmitter(FVector pos);
virtual void Tick() override;
virtual void Draw(s32 cameraId) override;
void func_80086700(s32 objectIndex);
void func_80086940(s32 objectIndex);
void func_80086C14(s32 objectIndex);
void func_80086C6C(s32 objectIndex);
void func_80077428(s32 objectIndex);
void func_80077584(s32 objectIndex);
void func_80077450(s32 objectIndex);
void func_80054AFC(s32 objectIndex, Vec3f arg1);
private:
+1 -1
View File
@@ -1205,7 +1205,7 @@ void update_gamestate(void) {
case ENDING:
gCurrentlyLoadedCourseId = COURSE_NULL;
init_segment_ending_sequences();
load_ceremony_cutscene();
setup_podium_ceremony();
break;
case CREDITS_SEQUENCE:
gCurrentlyLoadedCourseId = COURSE_NULL;
+81 -3
View File
@@ -31,8 +31,11 @@
#include "engine/courses/PodiumCeremony.h"
#include "engine/GarbageCollector.h"
#include "engine/TrainCrossing.h"
#include "src/engine/objects/BombKart.h"
#include "engine/objects/BombKart.h"
#include "engine/objects/Lakitu.h"
#include "Smoke.h"
@@ -365,7 +368,7 @@ extern "C" {
}
}
void CourseManager_DrawActor(Camera* camera, struct Actor* actor) {
void CourseManager_DrawActors(Camera* camera, struct Actor* actor) {
AActor* a = gWorldInstance.ConvertActorToAActor(actor);
if (a->IsMod()) {
a->Draw(camera);
@@ -384,12 +387,32 @@ extern "C" {
}
}
// A couple objects such as lakitu are ticked inside of process_game_tick which support 60fps.
// This is a fallback to support that.
void CourseManager_TickObjects60fps() {
if (gWorldInstance.CurrentCourse) {
gWorldInstance.TickObjects60fps();
}
}
void CourseManager_DrawObjects(s32 cameraId) {
if (gWorldInstance.CurrentCourse) {
gWorldInstance.DrawObjects(cameraId);
}
}
void CM_TickParticles() {
if (gWorldInstance.CurrentCourse) {
gWorldInstance.TickParticles();
}
}
void CM_DrawParticles(s32 cameraId) {
if (gWorldInstance.CurrentCourse) {
gWorldInstance.DrawParticles(cameraId);
}
}
// Helps prevents users from forgetting to add a finishline to their course
bool cm_DoesFinishlineExist() {
for (AActor* actor : gWorldInstance.Actors) {
@@ -503,6 +526,50 @@ extern "C" {
}
}
/**
* This should only be ran once per course, otherwise animation/timings might become sped up.
*/
void CM_SpawnStarterLakitu() {
if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
return;
}
for (size_t i = 0; i < gPlayerCountSelection1; i++) {
OLakitu* lakitu = new OLakitu(i, OLakitu::LakituType::STARTER);
gWorldInstance.Lakitus[i] = lakitu;
gWorldInstance.AddObject(lakitu);
}
}
// Checkered flag lakitu
void CM_ActivateFinishLakitu(s32 playerId) {
if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
return;
}
gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::FINISH);
}
void CM_ActivateSecondLapLakitu(s32 playerId) {
if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
return;
}
gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::SECOND_LAP);
}
void CM_ActivateFinalLapLakitu(s32 playerId) {
if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
return;
}
gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::FINAL_LAP);
}
void CM_ActivateReverseLakitu(s32 playerId) {
if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
return;
}
gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::REVERSE);
}
extern Vec3su D_80165834;
void CourseManager_TickThwomps() {
// TickLights
@@ -614,8 +681,14 @@ extern "C" {
}
}
void m_ClearActors(void) {
/**
* Clean up actors and other game objects.
*/
void CM_CleanWorld(void) {
gWorldInstance.Actors.clear();
gWorldInstance.Objects.clear();
gWorldInstance.Emitters.clear();
gWorldInstance.Lakitus.clear();
}
struct Actor* m_AddBaseActor(void) {
@@ -737,6 +810,11 @@ extern "C" {
void* GetBattleCup(void) {
return gBattleCup;
}
// End of frame cleanup of actors, objects, etc.
void CM_RunGarbageCollector(void) {
RunGarbageCollector();
}
}
void push_frame() {
+14 -2
View File
@@ -43,15 +43,25 @@ void CourseManager_RenderCredits();
void CourseManager_SpawnActors();
void CM_SpawnStarterLakitu();
void CM_ActivateFinishLakitu(s32 playerId);
void CM_ActivateSecondLapLakitu(s32 playerId);
void CM_ActivateFinalLapLakitu(s32 playerId);
void CM_ActivateReverseLakitu(s32 playerId);
bool cm_DoesFinishlineExist();
void CourseManager_InitClouds();
void CourseManager_DrawActor(Camera* camera, struct Actor* actor);
void CourseManager_DrawActors(Camera* camera, struct Actor* actor);
void CourseManager_TickObjects();
void CourseManager_TickObjects60fps();
void CourseManager_DrawObjects(s32 cameraId);
void CM_TickParticles(void);
void CM_DrawParticles(s32 cameraId);
void CourseManager_UpdateClouds(s32 arg0, Camera* camera);
void CourseManager_Waypoints(Player* player, int8_t playerId);
@@ -149,7 +159,7 @@ struct Actor* m_AddBaseActor(void);
size_t m_GetActorSize();
size_t m_FindActorIndex(struct Actor* actor);
void m_ActorCollision(Player* player, struct Actor* actor);
void m_ClearActors(void);
void CM_CleanWorld(void);
void* GetMarioRaceway(void);
@@ -205,6 +215,8 @@ void* GetBattleCup(void);
void* GetCup();
void CM_RunGarbageCollector(void);
#ifdef __cplusplus
}
#endif
+2 -2
View File
@@ -1214,7 +1214,7 @@ void init_actors_and_load_textures(void) {
init_red_shell_texture();
destroy_all_actors();
m_ClearActors();
CM_CleanWorld();
spawn_course_actors();
CourseManager_VehiclesSpawn();
@@ -2428,7 +2428,7 @@ void render_course_actors(struct UnkStruct_800DC5EC* arg0) {
}
switch (actor->type) {
default: // Draw custom actor
CourseManager_DrawActor(D_800DC5EC->camera, actor);
CourseManager_DrawActors(D_800DC5EC->camera, actor);
break;
case ACTOR_TREE_MARIO_RACEWAY:
render_actor_tree_mario_raceway(camera, sBillBoardMtx, actor);
+9 -9
View File
@@ -489,7 +489,7 @@ u8* dma_textures(const char* texture, size_t arg1, size_t arg2) {
#ifdef TARGET_N64
temp_v0 = (u8*) gNextFreeMemoryAddress;
#else
//u8* tex = (u8*) LOAD_ASSET(texture);
u8* tex = (u8*) LOAD_ASSET(texture);
temp_v0 = (u8*) allocate_memory(arg2);
#endif
@@ -504,8 +504,8 @@ u8* dma_textures(const char* texture, size_t arg1, size_t arg2) {
mio0decode((u8*) temp_a0, temp_v0);
gNextFreeMemoryAddress += arg2;
#else
//memcpy(temp_v0, tex, arg2);
strcpy(temp_v0, texture);
memcpy(temp_v0, tex, arg2);
//strcpy(temp_v0, texture);
#endif
return temp_v0;
}
@@ -1483,10 +1483,6 @@ uintptr_t texSegEnd;
size_t texSegSize;
Gfx* testaaa;
/**
* @brief Loads & DMAs course data. Vtx, textures, displaylists, etc.
* @param courseId
*/
u8* load_lakitu_tlut_x64(const char** textureList, size_t length) {
// Calculate lakitu texture size to allocate
size_t size = 0;
@@ -1498,7 +1494,7 @@ u8* load_lakitu_tlut_x64(const char** textureList, size_t length) {
gNextFreeMemoryAddress += size;
size_t offset = 0;
for (size_t i = 0; i < length; i++) {
u8* tex = (u8*) LOAD_ASSET(textureList[i]);
u8* tex = (u8*) LOAD_ASSET_RAW(textureList[i]);
size_t texSize = ResourceGetTexSizeByName(textureList[i]);
// printf("\nTEX SIZE: %X\n\n", texSize);
memcpy(&textures[offset], tex, texSize);
@@ -1507,9 +1503,13 @@ u8* load_lakitu_tlut_x64(const char** textureList, size_t length) {
return textures;
}
/**
* @brief Loads & DMAs course data. Vtx, textures, displaylists, etc.
* @param courseId
*/
void load_course(s32 courseId) {
printf("Loading Course %d\n", courseId);
gNextFreeMemoryAddress = gFreeMemoryResetAnchor;
m_ClearActors();
CM_CleanWorld();
LoadCourse();
}
-1
View File
@@ -42,7 +42,6 @@ struct AllocOnlyPool {
extern f32 vtxStretchY;
u8* load_lakitu_textures_x64(const char** textureList, size_t length);
u8* load_lakitu_tlut_x64(const char** textureList, size_t length);
void* get_next_available_memory_addr(uintptr_t);
uintptr_t set_segment_base_addr(s32, void*);
+1 -1
View File
@@ -904,7 +904,7 @@ void func_8028FCBC(void) {
D_800DC510 = 2;
D_800DC5B0 = 0;
D_800DC5B8 = 1;
func_80078F64();
CM_SpawnStarterLakitu(); // func_80078F64();
if ((gModeSelection == TIME_TRIALS) && (D_80162DD6 == 0)) {
phi_v0_4 = 0x1;
for (i = 0; i < gCurrentCourseId; i++) {
-12
View File
@@ -3836,18 +3836,6 @@ void render_object_smoke_particles(s32 cameraId) {
}
}
void func_80054AFC(s32 objectIndex, Vec3f arg1) {
D_80183E80[0] = func_800418E8(gObjectList[objectIndex].pos[2], gObjectList[objectIndex].pos[1], arg1);
D_80183E80[1] = func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], arg1);
D_80183E80[2] = (u16) gObjectList[objectIndex].orientation[2];
func_8004B138((s32) gObjectList[objectIndex].unk_084[0], (s32) gObjectList[objectIndex].unk_084[1],
(s32) gObjectList[objectIndex].unk_084[2], (s32) gObjectList[objectIndex].primAlpha);
rsp_set_matrix_transformation(gObjectList[objectIndex].pos, (u16*) D_80183E80,
gObjectList[objectIndex].sizeScaling);
gSPVertex(gDisplayListHead++, D_0D005AE0, 4, 0);
gSPDisplayList(gDisplayListHead++, common_rectangle_display);
}
void func_80055164(s32 objectIndex) {
if (gObjectList[objectIndex].state >= 2) {
gSPDisplayList(gDisplayListHead++, D_0D0077A0);
-2
View File
@@ -358,7 +358,6 @@ void render_object_bowser_flame_particle(s32, s32);
void render_object_bowser_flame(s32);
void func_8005477C(s32, u8, Vec3f);
void render_object_smoke_particles(s32);
void func_80054AFC(s32, Vec3f);
void func_80054D00(s32, s32);
void func_80054E10(s32);
void func_80054EB8(s32);
@@ -381,7 +380,6 @@ void func_80055CCC(s32, s32);
void render_object_hot_air_balloon(s32);
void func_80055EF4(s32, s32);
void func_80055F48(s32);
void func_80055FA0(s32, s32);
void func_80056160(s32);
void render_object_neon(s32);
-230
View File
@@ -2206,160 +2206,6 @@ void init_smoke_particles(s32 arg0) {
}
}
void func_80077138(s32 objectIndex, Vec3f arg1, s32 arg2) {
s8 temp_v0_3;
Vec3s sp30;
init_object(objectIndex, arg2);
gObjectList[objectIndex].unk_0D5 = 0x0C;
gObjectList[objectIndex].sizeScaling = 0.05f;
set_obj_origin_pos(objectIndex, arg1[0], arg1[1], arg1[2]);
set_obj_orientation(objectIndex, 0U, 0U, 0U);
set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f);
switch (arg2) {
case 0:
gObjectList[objectIndex].velocity[1] = -1.0f;
gObjectList[objectIndex].unk_034 = (f32) ((random_int(0x004BU) * 0.01) + 0.25);
gObjectList[objectIndex].direction_angle[1] = random_int(0x0040U) << 0xA;
func_8008751C(objectIndex);
gObjectList[objectIndex].unk_084[5] = 0x001E;
break;
case 1:
gObjectList[objectIndex].velocity[1] = 1.5f;
gObjectList[objectIndex].unk_034 = (f32) ((random_int(0x0064U) * 0.01) + 0.5);
gObjectList[objectIndex].direction_angle[1] = random_int(0x0040U) << 0xA;
func_8008751C(objectIndex);
gObjectList[objectIndex].unk_084[5] = 0x0032;
break;
}
temp_v0_3 = random_int(0x000CU);
if (temp_v0_3 < 9) {
func_8005C674(temp_v0_3, &sp30[2], &sp30[1], sp30);
gObjectList[objectIndex].unk_048 = 0;
gObjectList[objectIndex].unk_084[0] = sp30[2];
gObjectList[objectIndex].unk_084[1] = sp30[1];
gObjectList[objectIndex].unk_084[2] = sp30[0];
} else {
temp_v0_3 = random_int(3U);
func_8005C6B4(temp_v0_3, &sp30[2], &sp30[1], sp30);
gObjectList[objectIndex].unk_084[0] = sp30[2];
gObjectList[objectIndex].unk_084[1] = sp30[1];
gObjectList[objectIndex].unk_084[2] = sp30[0];
gObjectList[objectIndex].unk_084[4] = temp_v0_3;
gObjectList[objectIndex].unk_048 = 1;
}
gObjectList[objectIndex].primAlpha = 0x00FF;
gObjectList[objectIndex].unk_084[3] = random_int(0x0800U) + 0x400;
if ((gObjectList[objectIndex].direction_angle[1] < 0x3000) ||
(gObjectList[objectIndex].direction_angle[1] >= 0xB001)) {
gObjectList[objectIndex].unk_084[3] = -gObjectList[objectIndex].unk_084[3];
}
}
void func_800773D8(f32* arg0, s32 arg1) {
s32 objectIndex = add_unused_obj_index(gObjectParticle3, &gNextFreeObjectParticle3, gObjectParticle3_SIZE);
if (objectIndex != NULL_OBJECT_ID) {
func_80077138(objectIndex, arg0, arg1);
}
}
void func_80077428(s32 arg0) {
object_next_state(arg0);
func_80086E70(arg0);
}
void func_80077450(s32 objectIndex) {
UNUSED s16 stackPadding0;
s16 sp3C;
s16 sp3A;
s16 sp38;
switch (gObjectList[objectIndex].state) {
case 0:
break;
case 1:
func_80077428(objectIndex);
break;
case 2:
f32_step_up_towards(&gObjectList[objectIndex].sizeScaling, 0.1f, 0.01f);
if ((gObjectList[objectIndex].pos[1] <= gObjectList[objectIndex].unk_084[5]) &&
(func_80073B00(objectIndex, &gObjectList[objectIndex].primAlpha, 0x000000FF, 0, 0x00000010, 0, 0) !=
0)) {
func_80086F60(objectIndex);
func_80072428(objectIndex);
}
break;
}
if (gObjectList[objectIndex].unk_048 != 0) {
gObjectList[objectIndex].unk_084[4] = (s16) ((s32) (gObjectList[objectIndex].unk_084[4] + 1) % 3);
func_8005C6B4(gObjectList[objectIndex].unk_084[4], &sp3C, &sp3A, &sp38);
gObjectList[objectIndex].unk_084[0] = sp3C;
gObjectList[objectIndex].unk_084[1] = sp3A;
gObjectList[objectIndex].unk_084[2] = sp38;
}
}
void func_80077584(s32 objectIndex) {
Object* object;
object = &gObjectList[objectIndex];
if ((object->unk_0AE != 0) && (object->unk_0AE == 1) && ((u8) object->unk_0D8 != 0)) {
if (object->velocity[1] >= -0.5) {
object->velocity[1] -= 0.15;
} else {
object->velocity[2] = 0.0f;
object->velocity[0] = 0.0f;
}
}
object->orientation[2] += object->unk_084[3];
object_add_velocity_offset_xyz(objectIndex);
object_calculate_new_pos_offset(objectIndex);
}
void func_80077640(void) {
s32 someIndex;
s32 objectIndex;
Object* object;
for (someIndex = 0; someIndex < gObjectParticle3_SIZE; someIndex++) {
objectIndex = gObjectParticle3[someIndex];
if (objectIndex != DELETED_OBJECT_ID) {
object = &gObjectList[objectIndex];
if (object->state != 0) {
func_80077450(objectIndex);
func_80077584(objectIndex);
if (object->state == 0) {
delete_object_wrapper(&gObjectParticle3[someIndex]);
}
}
}
}
}
void init_object_leaf_particle(s32 objectIndex, Vec3f arg1, s32 num) {
@@ -4375,54 +4221,6 @@ void func_8007DDC0(s32 objectIndex) {
}
}
void func_8007E1F4(s32 objectIndex) {
f32 sp2C;
Object* object;
@@ -4555,34 +4353,6 @@ void func_8008153C(s32 objectIndex) {
}
}
#ifdef NON_MATCHING
// https://decomp.me/scratch/PYAg4
// Stack issue caused by the `test` variable, but removing it causes much, much larger differences
-3
View File
@@ -160,9 +160,6 @@ void func_80076F2C(void);
void init_object_smoke_particle2(s32, s32);
void init_smoke_particles(s32);
void func_800773D8(f32*, s32);
void func_80077428(s32);
void func_80077450(s32);
void func_80077584(s32);
void func_80077640(void);
void init_object_leaf_particle(s32, Vec3f, s32);
s32 init_leaf_particle(Vec3f, s32);