mirror of
https://github.com/HarbourMasters/SpaghettiKart
synced 2026-08-17 21:53:17 -04:00
394 lines
15 KiB
C++
394 lines
15 KiB
C++
#include "Trophy.h"
|
|
#include "assets/common_data.h"
|
|
#include "assets/data_segment2.h"
|
|
extern "C" {
|
|
#include "main.h"
|
|
#include "defines.h"
|
|
#include "update_objects.h"
|
|
#include "code_80057C60.h"
|
|
#include "assets/ceremony_data.h"
|
|
#include "podium_ceremony_actors.h"
|
|
#include "math_util.h"
|
|
#include "math_util_2.h"
|
|
#include "data/some_data.h"
|
|
#include "engine/Matrix.h"
|
|
#include "render_objects.h"
|
|
#include "code_80086E70.h"
|
|
#include "code_80091750.h"
|
|
}
|
|
|
|
OTrophy::OTrophy(const FVector& pos, TrophyType trophy, Behaviour bhv) {
|
|
s32 objectIndex = indexObjectList1[3];
|
|
_trophy = trophy;
|
|
_spawnPos = pos;
|
|
_spawnPos.y += 16.0f; // Adjust the height so the trophy sits on the surface when positioned to 0,0,0
|
|
_bhv = bhv;
|
|
|
|
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:
|
|
gObjectList[objectIndex].model = (Gfx*)gold_trophy_dl10;
|
|
break;
|
|
case TrophyType::SILVER:
|
|
gObjectList[objectIndex].model = (Gfx*)gold_trophy_dl12;
|
|
break;
|
|
case TrophyType::BRONZE:
|
|
gObjectList[objectIndex].model = (Gfx*)gold_trophy_dl14;
|
|
break;
|
|
case TrophyType::GOLD_150:
|
|
gObjectList[objectIndex].model = (Gfx*)gold_trophy_dl11;
|
|
break;
|
|
case TrophyType::SILVER_150:
|
|
gObjectList[objectIndex].model = (Gfx*)gold_trophy_dl13;
|
|
break;
|
|
case TrophyType::BRONZE_150:
|
|
gObjectList[objectIndex].model = (Gfx*)gold_trophy_dl15;
|
|
break;
|
|
}
|
|
|
|
// Set defaults for modded behaviours
|
|
if (_bhv != OTrophy::Behaviour::PODIUM_CEREMONY) {
|
|
gObjectList[objectIndex].sizeScaling = 0.025f;
|
|
gObjectList[objectIndex].unk_084[1] = 0x0200;
|
|
object_next_state(objectIndex);
|
|
func_80086E70(objectIndex);
|
|
}
|
|
|
|
switch(_bhv) {
|
|
case OTrophy::Behaviour::GO_FISH:
|
|
gObjectList[objectIndex].sizeScaling = 0.010f;
|
|
break;
|
|
}
|
|
|
|
Object *object = &gObjectList[objectIndex];
|
|
object->origin_pos[0] = _spawnPos.x;
|
|
object->origin_pos[1] = _spawnPos.y;
|
|
object->origin_pos[2] = _spawnPos.z;
|
|
object->pos[0] = _spawnPos.x;
|
|
object->pos[1] = _spawnPos.y;
|
|
object->pos[2] = _spawnPos.z;
|
|
}
|
|
|
|
void OTrophy::Tick() { // func_80086D80
|
|
s32 objectIndex = indexObjectList1[3];
|
|
s32 var_s0;
|
|
|
|
// 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 && (*_toggleVisibility == true)) {
|
|
OTrophy::func_80086C14(objectIndex);
|
|
OTrophy::func_80086940(objectIndex);
|
|
if (D_801658F4 != 0) {
|
|
if (D_8016559C == 0) {
|
|
OTrophy::func_80086C6C(objectIndex);
|
|
}
|
|
} else {
|
|
for (var_s0 = 0; var_s0 < 2; var_s0++) {
|
|
OTrophy::func_80086C6C(objectIndex);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case OTrophy::Behaviour::STATIONARY:
|
|
if (gObjectList[objectIndex].state != 0) {
|
|
gObjectList[objectIndex].sizeScaling = 0.025f;
|
|
set_obj_origin_pos(objectIndex, _spawnPos.x,
|
|
_spawnPos.y + 16.0, _spawnPos.z);
|
|
set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f);
|
|
set_obj_direction_angle(objectIndex, 0U, 0U, 0U);
|
|
gObjectList[objectIndex].unk_084[1] = 0x0200;
|
|
object_next_state(objectIndex);
|
|
func_80086E70(objectIndex);
|
|
OTrophy::func_80086940(objectIndex);
|
|
}
|
|
break;
|
|
case OTrophy::Behaviour::ROTATE:
|
|
if (gObjectList[objectIndex].state != 0) {
|
|
|
|
gObjectList[objectIndex].direction_angle[0] += 0x400;
|
|
gObjectList[objectIndex].direction_angle[1] -= 0x200;
|
|
}
|
|
break;
|
|
case OTrophy::Behaviour::ROTATE2:
|
|
if (gObjectList[objectIndex].state != 0) {
|
|
|
|
gObjectList[objectIndex].direction_angle[0] += 0x400;
|
|
gObjectList[objectIndex].direction_angle[1] = 0xE800;
|
|
gObjectList[objectIndex].direction_angle[2] = 0xDA00;
|
|
}
|
|
break;
|
|
case OTrophy::Behaviour::GO_FISH:
|
|
if (gObjectList[objectIndex].state != 0) {
|
|
|
|
// Get the player's yaw
|
|
Player *player = &gPlayers[0];
|
|
float yaw = (player->rotation[1] + 0x4000) * (M_PI / 32768.0f); // Convert degrees to radians
|
|
|
|
// Calculate forward direction based on yaw (same as before)
|
|
float lookAtX = player->pos[0] + cos(yaw);
|
|
float lookAtZ = player->pos[2] + sin(yaw);
|
|
|
|
float forwardX = lookAtX - player->pos[0];
|
|
float forwardY = 0; // Optional: Ignore height changes
|
|
float forwardZ = lookAtZ - player->pos[2];
|
|
|
|
// Normalize the forward vector
|
|
float length = sqrtf(forwardX * forwardX + forwardZ * forwardZ);
|
|
if (length != 0) {
|
|
forwardX /= length;
|
|
forwardZ /= length;
|
|
}
|
|
|
|
float distance = 30.0f;
|
|
|
|
// Calculate the object's position in front of the player (same as before)
|
|
gObjectList[objectIndex].pos[0] = player->pos[0] + forwardX * distance;
|
|
gObjectList[objectIndex].pos[1] = player->pos[1] + 8.0f; // Optional height offset
|
|
gObjectList[objectIndex].pos[2] = player->pos[2] + forwardZ * distance;
|
|
|
|
// Apply more sensitive random movement based on player velocity to simulate floating behavior
|
|
float velocityFactor = 0.1f; // Increased factor for more sensitivity
|
|
gObjectList[objectIndex].pos[0] += player->velocity[0] * velocityFactor;
|
|
gObjectList[objectIndex].pos[1] += player->velocity[1] * velocityFactor; // Optional: Add vertical movement
|
|
gObjectList[objectIndex].pos[2] += player->velocity[2] * velocityFactor;
|
|
|
|
// Increase oscillation for more dynamic movement (sine wave effect)
|
|
float oscillationSpeed = 4.0f; // Increased speed for quicker oscillations
|
|
float oscillationAmplitude = 0.4f; // Increased amplitude for more noticeable movement
|
|
gObjectList[objectIndex].pos[1] += oscillationAmplitude * sinf(oscillationSpeed * gGlobalTimer); // Vertical oscillation based on time
|
|
|
|
// Now use smooth interpolation (lerp) to gradually move the trophy towards its target position
|
|
float lerpFactor = 0.25f; // Increased to make the trophy follow the player more quickly
|
|
|
|
gObjectList[objectIndex].pos[0] = _oldPos[0] + lerpFactor * (gObjectList[objectIndex].pos[0] - _oldPos[0]);
|
|
gObjectList[objectIndex].pos[1] = _oldPos[1] + lerpFactor * (gObjectList[objectIndex].pos[1] - _oldPos[1]);
|
|
gObjectList[objectIndex].pos[2] = _oldPos[2] + lerpFactor * (gObjectList[objectIndex].pos[2] - _oldPos[2]);
|
|
|
|
// Save the current position for the next frame
|
|
_oldPos[0] = gObjectList[objectIndex].pos[0];
|
|
_oldPos[1] = gObjectList[objectIndex].pos[1];
|
|
_oldPos[2] = gObjectList[objectIndex].pos[2];
|
|
|
|
|
|
gObjectList[objectIndex].direction_angle[0] += 0x400;
|
|
gObjectList[objectIndex].direction_angle[1] -= 0x200;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void OTrophy::Draw(s32 cameraId) {
|
|
s32 listIndex = indexObjectList1[3];
|
|
Mat4 someMatrix1;
|
|
Mat4 someMatrix2;
|
|
Object* object;
|
|
if (*_toggleVisibility == true) {
|
|
object = &gObjectList[listIndex];
|
|
if (object->state >= 2) {
|
|
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_LOAD | G_MTX_MODELVIEW);
|
|
mtxf_set_matrix_transformation(someMatrix1, object->pos, object->direction_angle, object->sizeScaling);
|
|
//convert_to_fixed_point_matrix(&gGfxPool->mtxHud[gMatrixHudCount], someMatrix1);
|
|
//gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxHud[gMatrixHudCount++]),
|
|
// G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW);
|
|
|
|
AddHudMatrix(someMatrix1, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW);
|
|
|
|
gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D0077A0);
|
|
gSPDisplayList(gDisplayListHead++, object->model);
|
|
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxLookAt[0]),
|
|
G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
|
|
mtxf_identity(someMatrix2);
|
|
render_set_position(someMatrix2, 0);
|
|
}
|
|
|
|
switch (_bhv) {
|
|
case GO_FISH:
|
|
size_t numTrophies = 0;
|
|
func_80057A50(40, 0, (char*) "Trophies Collected: ", (s16) numTrophies);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void OTrophy::func_80086700(s32 objectIndex) {
|
|
gObjectList[objectIndex].sizeScaling = 0.005f;
|
|
set_obj_origin_pos(objectIndex, gObjectList[indexObjectList2[0]].pos[0],
|
|
gObjectList[indexObjectList2[0]].pos[1] + 16.0, gObjectList[indexObjectList2[0]].pos[2]);
|
|
set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f);
|
|
set_obj_direction_angle(objectIndex, 0U, 0U, 0U);
|
|
gObjectList[objectIndex].unk_084[1] = 0x0200;
|
|
object_next_state(objectIndex);
|
|
func_80086E70(objectIndex);
|
|
}
|
|
|
|
void OTrophy::func_80086940(s32 objectIndex) {
|
|
Object* object;
|
|
|
|
object = &gObjectList[objectIndex];
|
|
switch (object->unk_0AE) {
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
func_80086FD4(objectIndex);
|
|
break;
|
|
case 2:
|
|
f32_step_towards(&object->sizeScaling, 0.025f, 0.001f);
|
|
func_80087C48(objectIndex, 6.0f, 0.1f, 0x000000C8);
|
|
if ((f64) object->velocity[1] <= 0.0) {
|
|
func_8008701C(objectIndex, 3);
|
|
}
|
|
break;
|
|
case 3:
|
|
func_800871AC(objectIndex, 0x00000064);
|
|
break;
|
|
case 4:
|
|
D_801658D6 = 1;
|
|
object->velocity[1] = -0.4f;
|
|
func_80086FD4(objectIndex);
|
|
// object->origin_pos[1] = 90.0f;
|
|
object->offset[1] = 60.0f;
|
|
// switch (D_802874D8.unk1D) {
|
|
// case 1:
|
|
// object->origin_pos[0] -= 3.0;
|
|
// object->origin_pos[2] += 15.0;
|
|
// break;
|
|
// case 2:
|
|
// object->origin_pos[0] -= 2.0;
|
|
// object->origin_pos[2] -= 15.0;
|
|
// break;
|
|
// }
|
|
break;
|
|
case 5:
|
|
if ((f64) object->offset[1] <= 8.0) {
|
|
f32_step_towards(&object->velocity[1], -0.1f, -0.01f);
|
|
}
|
|
object_add_velocity_offset_y(objectIndex);
|
|
if ((f64) object->offset[1] <= 0.0) {
|
|
func_80086FD4(objectIndex);
|
|
}
|
|
break;
|
|
case 6:
|
|
if (func_800871AC(objectIndex, 0x00000041) != 0) {
|
|
D_801658F4 = 1;
|
|
}
|
|
break;
|
|
case 7:
|
|
if (func_800871AC(objectIndex, 0x00000064) != 0) {
|
|
func_8009265C();
|
|
func_80086F60(objectIndex);
|
|
}
|
|
break;
|
|
}
|
|
if (D_801658D6 != 0) {
|
|
object->direction_angle[0] += 0x400;
|
|
object->direction_angle[1] = 0xE800;
|
|
object->direction_angle[2] = 0xDA00;
|
|
} else {
|
|
object->direction_angle[0] += 0x400;
|
|
object->direction_angle[1] -= 0x200;
|
|
}
|
|
object_calculate_new_pos_offset(objectIndex);
|
|
}
|
|
|
|
void OTrophy::func_80086C14(s32 objectIndex) {
|
|
switch (gObjectList[objectIndex].state) { /* irregular */
|
|
case 1:
|
|
OTrophy::func_80086700(objectIndex);
|
|
break;
|
|
case 0:
|
|
case 2:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void OTrophy::func_80086C6C(s32 objectIndex) {
|
|
Vec3f sp24;
|
|
|
|
sp24[0] = (gObjectList[objectIndex].pos[0] - 5.0f) + random_int(0x000AU);
|
|
sp24[2] = (gObjectList[objectIndex].pos[2] - 5.0f) + random_int(0x000AU);
|
|
if (D_801658F4 != 0) {
|
|
sp24[1] = gObjectList[objectIndex].pos[1] + 14.0;
|
|
} else {
|
|
sp24[1] = gObjectList[objectIndex].pos[1] - 2.0;
|
|
}
|
|
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];
|
|
}
|
|
} |