diff options
Diffstat (limited to 'src/engine/objects')
| -rw-r--r-- | src/engine/objects/Trophy.cpp | 335 | ||||
| -rw-r--r-- | src/engine/objects/Trophy.h | 55 |
2 files changed, 390 insertions, 0 deletions
diff --git a/src/engine/objects/Trophy.cpp b/src/engine/objects/Trophy.cpp new file mode 100644 index 000000000..464a2277c --- /dev/null +++ b/src/engine/objects/Trophy.cpp @@ -0,0 +1,335 @@ +#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; + + 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; + } + + 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; + 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; + + // if ((D_801658CE != 0) && (D_801658DC == 0)) { + // temp_s2 = indexObjectList1[3]; + // init_object(temp_s2, 0); + // D_801658DC = 1; + // } + + switch(_bhv) { + case OTrophy::Behaviour::PODIUM_CEREMONY: + if (gObjectList[objectIndex].state != 0) { + 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) { + 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); +} diff --git a/src/engine/objects/Trophy.h b/src/engine/objects/Trophy.h new file mode 100644 index 000000000..76834d77e --- /dev/null +++ b/src/engine/objects/Trophy.h @@ -0,0 +1,55 @@ +#pragma once + +#include <libultraship.h> +#include <vector> +#include "Object.h" + +extern "C" { +#include "macros.h" +#include "main.h" +#include "vehicles.h" +#include "waypoints.h" +#include "common_structs.h" +#include "objects.h" +#include "course_offsets.h" +#include "some_data.h" +} + + +class OTrophy : public OObject { +public: + enum TrophyType { + BRONZE, + SILVER, + GOLD, + BRONZE_150, + SILVER_150, + GOLD_150, + }; + + enum Behaviour { + PODIUM_CEREMONY, + STATIONARY, + ROTATE, // A dual-axis opposing rotation + ROTATE2, // A single-axis rotation + GO_FISH, + }; + + explicit OTrophy(const FVector& pos, TrophyType trophy, Behaviour bhv); + + 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); + +private: + + s32 _idx; + TrophyType _trophy; + FVector _spawnPos; + Behaviour _bhv; + int8_t *_toggleVisibility; + Vec3f _oldPos; +}; |
