summaryrefslogtreecommitdiff
path: root/src/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/World.cpp20
-rw-r--r--src/engine/World.h12
-rw-r--r--src/engine/objects/Trophy.cpp335
-rw-r--r--src/engine/objects/Trophy.h55
4 files changed, 407 insertions, 15 deletions
diff --git a/src/engine/World.cpp b/src/engine/World.cpp
index ead375a24..429b402a0 100644
--- a/src/engine/World.cpp
+++ b/src/engine/World.cpp
@@ -13,7 +13,7 @@
#include "objects/Penguin.h"
#include "TrainCrossing.h"
#include <memory>
-#include "objects/GameObject.h"
+#include "objects/Object.h"
extern "C" {
#include "camera.h"
@@ -242,7 +242,7 @@ void RemoveExpiredActors() {
// Actors.end());
}
-GameObject* World::AddObject(GameObject* object) {
+OObject* World::AddObject(OObject* object) {
Objects.push_back(object);
return Objects.back();
}
@@ -253,17 +253,17 @@ void World::TickObjects() {
}
}
-void World::DrawObjects(Camera *camera) {
+void World::DrawObjects(s32 cameraId) {
for (const auto& object : Objects) {
- object->Draw(camera);
+ object->Draw(cameraId);
}
}
void World::ExpiredObjects() {
- //this->GameObjects.erase(
- // std::remove_if(this->GameObjects.begin(), this->GameObjects.end(),
- // [](const std::unique_ptr<GameObject>& object) { return object->uuid == 0; }), // Example condition
- // this->GameObjects.end());
+ //this->Objects.erase(
+ // std::remove_if(this->Objects.begin(), this->Objects.end(),
+ // [](const std::unique_ptr<OObject>& object) { return object->uuid == 0; }), // Example condition
+ // this->Objects.end());
}
void World::DestroyObjects() {
@@ -271,9 +271,9 @@ void World::DestroyObjects() {
}
Object* World::GetObjectByIndex(size_t index) {
- //if (index < this->GameObjects.size()) {
+ //if (index < this->Objects.size()) {
// Assuming GameActor::a is accessible, use reinterpret_cast if needed
- // return reinterpret_cast<Object*>(&this->GameObjects[index]->o);
+ // return reinterpret_cast<Object*>(&this->Objects[index]->o);
//}
return nullptr; // Or handle the error as needed
}
diff --git a/src/engine/World.h b/src/engine/World.h
index 2ae4462f4..3b48284e8 100644
--- a/src/engine/World.h
+++ b/src/engine/World.h
@@ -1,7 +1,7 @@
#pragma once
#include <libultraship.h>
-#include "objects/GameObject.h"
+#include "objects/Object.h"
#include "Cup.h"
#include "vehicles/Vehicle.h"
#include "vehicles/Train.h"
@@ -14,6 +14,7 @@
#include "objects/Seagull.h"
#include <memory>
#include "Actor.h"
+#include "particles/ParticleEmitter.h"
extern "C" {
#include "camera.h"
@@ -21,7 +22,7 @@ extern "C" {
#include "engine/Engine.h"
};
-class GameObject;
+class OObject;
class Cup; // <-- Forward declaration
class Course;
class AVehicle;
@@ -95,11 +96,11 @@ public:
AActor* ConvertActorToAActor(Actor* actor);
Actor* ConvertAActorToActor(AActor* actor);
- GameObject* AddObject(GameObject* object);
+ OObject* AddObject(OObject* object);
CProperties* GetCourseProps();
void TickObjects();
- void DrawObjects(Camera *camera);
+ void DrawObjects(s32 cameraId);
void ExpiredObjects();
void DestroyObjects();
Object *GetObjectByIndex(size_t);
@@ -131,7 +132,8 @@ public:
size_t CupIndex = 1;
std::vector<AActor*> Actors;
- std::vector<GameObject*> Objects;
+ std::vector<OObject*> Objects;
+ std::vector<ParticleEmitter*> Emitters;
/** Actors */
void AddBoat(f32 speed, uint32_t waypoint);
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;
+};