summaryrefslogtreecommitdiff
path: root/src/engine/objects
diff options
context:
space:
mode:
authorMegaMech <MegaMech@users.noreply.github.com>2025-01-18 08:58:12 -0700
committerGitHub <noreply@github.com>2025-01-18 08:58:12 -0700
commit8c46368d5d93ad278c124ffc6446ab691dff8082 (patch)
tree3506dce3de08c514eeb3ee9d1dc575e7713331ca /src/engine/objects
parent04d56d6ba0705776149358608a27db8ab23e9449 (diff)
Fix data, option menus, impl boos, fix demo camera (#156)
* Fix data and option menus * safer code * wip boos impl * finish impl boos * Fix demo camera * slightly better match
Diffstat (limited to 'src/engine/objects')
-rw-r--r--src/engine/objects/Boos.cpp272
-rw-r--r--src/engine/objects/Boos.h75
2 files changed, 347 insertions, 0 deletions
diff --git a/src/engine/objects/Boos.cpp b/src/engine/objects/Boos.cpp
new file mode 100644
index 000000000..0e64c673e
--- /dev/null
+++ b/src/engine/objects/Boos.cpp
@@ -0,0 +1,272 @@
+#include "Boos.h"
+#include "World.h"
+#include "CoreMath.h"
+
+extern "C" {
+#include "render_objects.h"
+#include "update_objects.h"
+#include "assets/banshee_boardwalk_data.h"
+#include "assets/common_data.h"
+#include "assets/boo_frames.h"
+#include "assets/other_textures.h"
+#include "math_util.h"
+#include "math_util_2.h"
+#include "code_80086E70.h"
+#include "code_80057C60.h"
+#include "code_800029B0.h"
+#include "code_80005FD0.h"
+#include "menus.h"
+#include "race_logic.h"
+#include "external.h"
+}
+
+size_t OBoos::_count = 0;
+
+OBoos::OBoos(size_t numBoos, const IPathSpan& leftBoundary, const IPathSpan& active, const IPathSpan& rightBoundary) {
+ // Max five boos allowed due to limited splines
+ // D_800E5D9C
+ if (numBoos > 10) {
+ printf("Boos.cpp: Only 10 boos allowed.\n");
+ numBoos = 10;
+ }
+
+ _indices.resize(numBoos, 0);
+
+
+ // Generate objects
+ for (size_t i = 0; i < numBoos; i++) {
+ find_unused_obj_index(&_indices[i]);
+ }
+
+ _numBoos = numBoos;
+ _leftBoundary = leftBoundary;
+ _active = active;
+ _rightBoundary = rightBoundary;
+}
+
+void OBoos::Tick() {
+ u16 temp_t4;
+ s32 objectIndex;
+ Player* player;
+ Camera* camera;
+ Object* object;
+
+ OBoos::func_8007CA70();
+ for (size_t i = 0; i < _numBoos; i++) {
+ objectIndex = _indices[i]; //indexObjectList3[i];
+ object = &gObjectList[objectIndex];
+ if (object->state != 0) {
+ func_8007C684(objectIndex);
+ func_8008B78C(objectIndex);
+ player = &gPlayerOne[object->unk_0D1];
+ camera = &camera1[object->unk_0D1];
+ temp_t4 = (0x8000 - camera->rot[1]);
+ object->pos[0] = player->pos[0] + (coss(temp_t4) * (object->origin_pos[0] + object->offset[0])) -
+ (sins(temp_t4) * (object->origin_pos[2] + object->offset[2]));
+ object->pos[1] = 6.5 + player->unk_074 + object->origin_pos[1] + object->offset[1];
+ object->pos[2] = player->pos[2] + (sins(temp_t4) * (object->origin_pos[0] + object->offset[0])) +
+ (coss(temp_t4) * (object->origin_pos[2] + object->offset[2]));
+ OBoos::func_8007C550(objectIndex);
+ if (is_obj_flag_status_active(objectIndex, 0x00000080) != 0) {
+ object->vertex = D_800E44B0;
+ } else {
+ object->vertex = D_800E4470;
+ }
+ }
+ }
+}
+
+void OBoos::Draw(s32 cameraId) {
+ u32 temp_s2;
+ s32 objectIndex;
+
+ for (size_t i = 0; i < _numBoos; i++) {
+ objectIndex = _indices[i]; //indexObjectList3[i];
+ if (gObjectList[objectIndex].state >= 2) {
+ temp_s2 = func_8008A364(objectIndex, cameraId, 0x4000U, 0x00000320);
+ if (CVarGetInteger("gNoCulling", 0) == 1) {
+ temp_s2 = MIN(temp_s2, 0x15F91U);
+ }
+ if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) {
+ func_800523B8(objectIndex, cameraId, temp_s2);
+ }
+ }
+ }
+}
+
+void OBoos::func_800523B8(s32 objectIndex, s32 arg1, u32 arg2) {
+ UNUSED s32 pad[2];
+ Object* object;
+ Camera* camera = &camera1[arg1];
+
+ object = &gObjectList[objectIndex];
+ object->orientation[1] = func_800418AC(object->pos[0], object->pos[2], camera->pos);
+ func_800484BC(object->pos, object->orientation, object->sizeScaling, object->primAlpha, (u8*) object->activeTLUT,
+ (u8*)object->activeTexture, object->vertex, 0x00000030, 0x00000028, 0x00000030, 0x00000028);
+ if ((is_obj_flag_status_active(objectIndex, 0x00000020) != 0) && (arg2 < 0x15F91U)) {
+ func_8004A630(&D_8018C830, object->pos, 0.4f);
+ }
+}
+
+void OBoos::func_8007CA70(void) {
+ // wtf is up with this pointer? Its such a dumb way of going about things
+ u16* point;
+
+ if (_isActive == false) {
+ _playerId = OBoos::func_8007C9F8();
+ point = &gNearestWaypointByPlayerId[_playerId];
+ printf("point %d\n", *point);
+ if ((*point > _active.Start) && (*point < _active.End)) {
+ // First group entrance
+ OBoos::BooStart(0, _playerId);
+ }
+ }
+ if (_isActive == true) {
+ point = &gNearestWaypointByPlayerId[_playerId];
+ printf("point %d\n", *point);
+
+ if ((*point > _leftBoundary.Start) && (*point < _leftBoundary.End)) {
+ // First group exit reverse direction
+ OBoos::BooExit(0);
+ }
+ if ((*point > _rightBoundary.Start) && (*point < _rightBoundary.End)) {
+ // First group exit
+ OBoos::BooExit(0);
+ }
+ }
+}
+
+void OBoos::func_8007C5B4(s32 objectIndex) {
+ Object* object;
+
+ init_texture_object(objectIndex, (u8*)d_course_banshee_boardwalk_boo_tlut, gTextureGhosts, 48, 40);
+ object = &gObjectList[objectIndex];
+ object->pos[0] = 0.0f;
+ object->pos[1] = 0.0f;
+ object->pos[2] = 0.0f;
+ set_object_flag(objectIndex, 0x00000020);
+ object_next_state(objectIndex);
+ object->primAlpha = 0;
+ func_80073844(objectIndex);
+ object->sizeScaling = 0.15f;
+ object->unk_034 = 1.0f;
+ func_80073FD4(objectIndex);
+ func_80086EF0(objectIndex);
+ set_object_flag(objectIndex, 0x00000800);
+ object->orientation[0] = 0;
+ object->orientation[2] = 0x8000;
+}
+
+void OBoos::func_8007C684(s32 objectIndex) {
+ switch (gObjectList[objectIndex].state) {
+ case 0:
+ break;
+ case 1:
+ OBoos::func_8007C5B4(objectIndex);
+ break;
+ }
+ if (gObjectList[objectIndex].state >= 2) {
+ switch (gObjectList[objectIndex].unk_0DC) {
+ case 0:
+ break;
+ case 1:
+ func_80073998(objectIndex, &gObjectList[objectIndex].primAlpha, 0, 0x00000050, 2, 1, 0);
+ break;
+ case 2:
+ func_80073CB0(objectIndex, &gObjectList[objectIndex].primAlpha, 0x00000050, 0x00000078, 1, 0, -1);
+ break;
+ case 3:
+ func_80073DC0(objectIndex, &gObjectList[objectIndex].primAlpha, 0, 2);
+ break;
+ case 4:
+ func_80072428(objectIndex);
+ func_80086F60(objectIndex);
+ func_80073884(objectIndex);
+ break;
+ }
+ func_80073514(objectIndex);
+ }
+}
+
+void OBoos::func_8007C4A4(s32 objectIndex) {
+ u16 var_t9;
+
+ var_t9 = gObjectList[objectIndex].direction_angle[1] * 0x24 / 0x10000;
+
+ if (var_t9 < 0x13) {
+ clear_object_flag(objectIndex, 0x80);
+ gObjectList[objectIndex].textureListIndex = var_t9;
+ } else {
+ set_object_flag(objectIndex, 0x80);
+ gObjectList[objectIndex].textureListIndex = 0x24 - var_t9;
+ }
+}
+
+void OBoos::func_8007C550(s32 objectIndex) {
+ gObjectList[objectIndex].direction_angle[1] =
+ func_800417B4(gObjectList[objectIndex].direction_angle[1],
+ atan2s(gObjectList[objectIndex].velocity[0], gObjectList[objectIndex].velocity[2]));
+ OBoos::func_8007C4A4(objectIndex);
+}
+
+s32 OBoos::func_8007C9F8(void) {
+ s32 ret;
+ s32 first, second;
+ if (gPlayerCount == 1) {
+ ret = 0;
+ } else {
+ if (gPlayerCount == 2) {
+ if (gModeSelection == 0) {
+ first = gGPCurrentRaceRankByPlayerId[0];
+ second = gGPCurrentRaceRankByPlayerId[1];
+ if (first < second) {
+ ret = 0;
+ } else {
+ ret = 1;
+ }
+ } else {
+ ret = gGPCurrentRacePlayerIdByRank[0];
+ }
+ } else {
+ ret = gGPCurrentRacePlayerIdByRank[0];
+ }
+ }
+ return ret;
+}
+
+void OBoos::BooStart(s32 group, s32 playerId) {
+ s32 objectIndex;
+ s16 temp_s1_2;
+ s16 temp_s4;
+ s16 temp_s5;
+ SplineData* spline;
+printf("Boo Start\n");
+ for (size_t i = 0; i < _numBoos; i++) {
+ objectIndex = _indices[i]; // indexObjectList3[group + i];
+ init_object(objectIndex, 1);
+ gObjectList[objectIndex].unk_0D1 = playerId;
+ temp_s1_2 = random_int(0x003CU) - 0x1E;
+ temp_s4 = random_int(0x0014U) - 0xA;
+ temp_s5 = random_int(0x0050U) - 0x28;
+ random_int(0x1000U);
+ spline = D_800E5D9C[i];
+ gObjectList[objectIndex].spline = spline;
+ gObjectList[objectIndex].origin_pos[0] = (f32) temp_s1_2;
+ gObjectList[objectIndex].origin_pos[1] = (f32) temp_s4;
+ gObjectList[objectIndex].origin_pos[2] = (f32) temp_s5;
+ }
+ func_800C9060(playerId, 0x1900705AU);
+
+ _isActive = true;
+}
+
+void OBoos::BooExit(s32 group) {
+ s32 objectIndex;
+printf("Boo Exit\n");
+ for (size_t i = 0; i < _numBoos; i++) {
+ objectIndex = _indices[i]; //indexObjectList3[group + temp_a0];
+ gObjectList[objectIndex].unk_0DC += 1;
+ }
+
+ _isActive = false;
+}
diff --git a/src/engine/objects/Boos.h b/src/engine/objects/Boos.h
new file mode 100644
index 000000000..cc49df474
--- /dev/null
+++ b/src/engine/objects/Boos.h
@@ -0,0 +1,75 @@
+#pragma once
+
+#include <libultraship.h>
+#include <vector>
+#include "Object.h"
+
+#include "World.h"
+#include "CoreMath.h"
+
+extern "C" {
+#include "macros.h"
+#include "main.h"
+#include "vehicles.h"
+#include "waypoints.h"
+#include "common_structs.h"
+#include "objects.h"
+#include "camera.h"
+#include "some_data.h"
+}
+
+/**
+ * OBoos
+ *
+ * Args use path indices or path points. Recommended to use a span of 10
+ * for each IPathSpan as that's how the original game did it. Ex. IPathSpan(10, 20)
+ *
+ * Once boos are active, they do not deactivate until the player drives into leftBoundary
+ * or rightBoundary. leftBoundary is really only used to deactivate the boos when the player is
+ * driving in the reverse direction.
+ *
+ * @arg numBoos to show, default 5, maximum 10 allowed due to limited splines
+ * @arg leftBoundary When the player enters this area, deactivate the boos.
+ * @arg active When the player enters this area, activate the boos.
+ * @arg rightBoundary When the player enters this area, deactivate the boos.
+ *
+ */
+class OBoos : public OObject {
+public:
+ explicit OBoos(size_t numBoos, const IPathSpan& leftBoundary, const IPathSpan& active, const IPathSpan& rightBoundary);
+
+ ~OBoos() {
+ _count--;
+ }
+
+ static size_t GetCount() {
+ return _count;
+ }
+
+ virtual void Tick() override;
+ virtual void Draw(s32 cameraId) override;
+ void func_800523B8(s32 objectIndex, s32 arg1, u32 arg2);
+
+ void func_8007CA70(void);
+ void func_8007C5B4(s32 objectIndex);
+ void func_8007C684(s32 objectIndex);
+ void func_8007C4A4(s32 objectIndex);
+ s32 func_8007C9F8(void);
+ void BooStart(s32 someIndex, s32 arg1);
+ void BooExit(s32 someIndex);
+ void func_8007C550(s32 objectIndex);
+
+private:
+ FVector _pos;
+ static size_t _count;
+ size_t _idx;
+ std::vector<s32> _indices; // indices into gObjectList
+ size_t _numBoos;
+
+ bool _isActive = false;
+ s32 _playerId = 0;
+
+ IPathSpan _leftBoundary;
+ IPathSpan _active;
+ IPathSpan _rightBoundary;
+};