From 6e760ee558c47052b69277e5525ed2393a13a0d4 Mon Sep 17 00:00:00 2001 From: elijah-thomas774 Date: Fri, 28 Nov 2025 17:49:23 -0500 Subject: [PATCH] d_t_spore Mostly there --- config/SOUE01/rels/d_t_sporeNP/symbols.txt | 52 ++-- include/d/a/obj/d_a_obj_spore.h | 13 + include/d/d_camera.h | 7 +- include/d/d_sc_game.h | 2 +- include/d/t/d_t_spore.h | 51 +++- src/REL/d/t/d_t_spore.cpp | 262 ++++++++++++++++++++- 6 files changed, 354 insertions(+), 33 deletions(-) create mode 100644 include/d/a/obj/d_a_obj_spore.h diff --git a/config/SOUE01/rels/d_t_sporeNP/symbols.txt b/config/SOUE01/rels/d_t_sporeNP/symbols.txt index e4af62d0..f4c61da5 100644 --- a/config/SOUE01/rels/d_t_sporeNP/symbols.txt +++ b/config/SOUE01/rels/d_t_sporeNP/symbols.txt @@ -3,29 +3,29 @@ _epilog = .text:0x00000030; // type:function size:0x2C scope:global _unresolved = .text:0x00000060; // type:function size:0x4 scope:global __register_global_object = .text:0x00000070; // type:function size:0x1C scope:global __destroy_global_chain = .text:0x00000090; // type:function size:0x54 scope:global -fn_454_F0 = .text:0x000000F0; // type:function size:0x40 +__dt__7mVec3_cFv = .text:0x000000F0; // type:function size:0x40 dSporeTag_c_classInit__Fv = .text:0x00000130; // type:function size:0x110 -__dt__11dSporeTag_cFv = .text:0x00000240; // type:function size:0x58 +__dt__5dTg_cFv = .text:0x00000240; // type:function size:0x58 __dt__24sFState_c<11dSporeTag_c>Fv = .text:0x000002A0; // type:function size:0x58 __dt__27sFStateFct_c<11dSporeTag_c>Fv = .text:0x00000300; // type:function size:0x6C __dt__80sStateMgr_c<11dSporeTag_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>Fv = .text:0x00000370; // type:function size:0xA0 __dt__50sFStateMgr_c<11dSporeTag_c,20sStateMethodUsr_FI_c>Fv = .text:0x00000410; // type:function size:0xA4 -fn_454_4C0 = .text:0x000004C0; // type:function size:0x4 -fn_454_4D0 = .text:0x000004D0; // type:function size:0x74 -SporeTag__initModels = .text:0x00000550; // type:function size:0x6C -SporeTag__init = .text:0x000005C0; // type:function size:0x94 +__ct__7mVec3_cFv = .text:0x000004C0; // type:function size:0x4 +__dt__12dSporeProc_cFv = .text:0x000004D0; // type:function size:0x74 +createHeap__11dSporeTag_cFv = .text:0x00000550; // type:function size:0x6C +create__11dSporeTag_cFv = .text:0x000005C0; // type:function size:0x94 changeState__80sStateMgr_c<11dSporeTag_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>FRC12sStateIDIf_c = .text:0x00000660; // type:function size:0x10 -fn_454_670 = .text:0x00000670; // type:function size:0x8 -fn_454_680 = .text:0x00000680; // type:function size:0x30 +doDelete__11dSporeTag_cFv = .text:0x00000670; // type:function size:0x8 +actorExecuteInEvent__11dSporeTag_cFv = .text:0x00000680; // type:function size:0x30 executeState__80sStateMgr_c<11dSporeTag_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>Fv = .text:0x000006B0; // type:function size:0x10 -SporeTag__update = .text:0x000006C0; // type:function size:0x30 -fn_454_6F0 = .text:0x000006F0; // type:function size:0x34 -fn_454_730 = .text:0x00000730; // type:function size:0x954 -fn_454_1090 = .text:0x00001090; // type:function size:0x318 +actorExecute__11dSporeTag_cFv = .text:0x000006C0; // type:function size:0x30 +draw__11dSporeTag_cFv = .text:0x000006F0; // type:function size:0x34 +execute__12dSporeProc_cFv = .text:0x00000730; // type:function size:0x954 +drawXlu__12dSporeProc_cFv = .text:0x00001090; // type:function size:0x318 initializeState_Wait__11dSporeTag_cFv = .text:0x000013B0; // type:function size:0x4 executeState_Wait__11dSporeTag_cFv = .text:0x000013C0; // type:function size:0x8 finalizeState_Wait__11dSporeTag_cFv = .text:0x000013D0; // type:function size:0x4 -fn_454_13E0 = .text:0x000013E0; // type:function size:0xF4 +__dt__11dSporeTag_cFv = .text:0x000013E0; // type:function size:0xF4 getStateID__80sStateMgr_c<11dSporeTag_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>CFv = .text:0x000014E0; // type:function size:0x10 build__27sFStateFct_c<11dSporeTag_c>FRC12sStateIDIf_c = .text:0x000014F0; // type:function size:0x60 dispose__27sFStateFct_c<11dSporeTag_c>FRP10sStateIf_c = .text:0x00001550; // type:function size:0xC @@ -47,18 +47,18 @@ isSameName__26sFStateID_c<11dSporeTag_c>CFPCc = .text:0x00001820; // type:functi _ctors = .ctors:0x00000000; // type:label scope:global _dtors = .dtors:0x00000000; // type:label scope:global __destroy_global_chain_reference = .dtors:0x00000000; // type:object size:0x4 scope:global -lbl_454_rodata_0 = .rodata:0x00000000; // type:object size:0xD0 data:float +lbl_454_rodata_0 = .rodata:0x00000000; // type:object size:0xD0 scope:local data:float g_profile_SPORE_TAG = .data:0x00000000; // type:object size:0x10 data:4byte -lbl_454_data_10 = .data:0x00000010; // type:object size:0x7 data:string -lbl_454_data_18 = .data:0x00000018; // type:object size:0x13 data:string -lbl_454_data_2C = .data:0x0000002C; // type:object size:0x19 data:string -SporeTag__vtable = .data:0x00000048; // type:object size:0x78 -lbl_454_data_C0 = .data:0x000000C0; // type:object size:0x30 -lbl_454_data_F0 = .data:0x000000F0; // type:object size:0x30 -lbl_454_data_120 = .data:0x00000120; // type:object size:0x18 -lbl_454_data_138 = .data:0x00000138; // type:object size:0x18 -lbl_454_data_150 = .data:0x00000150; // type:object size:0xE0 -lbl_454_data_230 = .data:0x00000230; // type:object size:0x34 +lbl_454_data_10 = .data:0x00000010; // type:object size:0x7 scope:local data:string +lbl_454_data_18 = .data:0x00000018; // type:object size:0x13 scope:local data:string +lbl_454_data_2C = .data:0x0000002C; // type:object size:0x19 scope:local data:string +__vt__11dSporeTag_c = .data:0x00000048; // type:object size:0x78 +lbl_454_data_C0 = .data:0x000000C0; // type:object size:0x30 scope:local +lbl_454_data_F0 = .data:0x000000F0; // type:object size:0x30 scope:local +lbl_454_data_120 = .data:0x00000120; // type:object size:0x18 scope:local +lbl_454_data_138 = .data:0x00000138; // type:object size:0x18 scope:local +lbl_454_data_150 = .data:0x00000150; // type:object size:0xE0 scope:local +lbl_454_data_230 = .data:0x00000230; // type:object size:0x34 scope:local __global_destructor_chain = .bss:0x00000000; // type:object size:0x4 scope:global -lbl_454_bss_8 = .bss:0x00000008; // type:object size:0x10 -SporeTag__StateID_Wait = .bss:0x00000018; // type:object size:0x30 data:4byte +lbl_454_bss_8 = .bss:0x00000008; // type:object size:0x10 scope:local +StateID_Wait__11dSporeTag_c = .bss:0x00000018; // type:object size:0x30 data:4byte diff --git a/include/d/a/obj/d_a_obj_spore.h b/include/d/a/obj/d_a_obj_spore.h new file mode 100644 index 00000000..1f787c6e --- /dev/null +++ b/include/d/a/obj/d_a_obj_spore.h @@ -0,0 +1,13 @@ +#ifndef D_A_O_SPORE_H +#define D_A_O_SPORE_H + +#include "d/a/obj/d_a_obj_base.h" +class dAcOSpore_c : public dAcObjBase_c { +public: + dAcOSpore_c() {} + virtual ~dAcOSpore_c() {} + +private: +}; + +#endif diff --git a/include/d/d_camera.h b/include/d/d_camera.h index 2bbdf40b..8f4560a0 100644 --- a/include/d/d_camera.h +++ b/include/d/d_camera.h @@ -29,6 +29,9 @@ public: const mVec3_c &getField_0x78() const { return field_0x78; } + f32 getField_0x2A8() const { + return field_0x2A8; + } mAng getYRot() const; bool doFn_800918E0(s32 a1, s16 a2) { @@ -66,7 +69,9 @@ private: /* 0x068 */ u8 _0x068[0x6C - 0x068]; /* 0x06C */ mVec3_c mPositionMaybe; /* 0x078 */ mVec3_c field_0x78; - /* 0x084 */ u8 _0x084[0xD98 - 0x084]; + /* 0x084 */ u8 _0x084[0x2A8 - 0x084]; + /* 0x2A8 */ f32 field_0x2A8; + /* 0x2AC */ u8 _0x2AC[0xD98 - 0x2AC]; /* 0xD98 */ void *field_0xD98; /* 0xD9C */ u8 _0xD9C[0xDA0 - 0xD9C]; /* 0xDA0 */ void *field_0xDA0; diff --git a/include/d/d_sc_game.h b/include/d/d_sc_game.h index af9973dd..d1a905b7 100644 --- a/include/d/d_sc_game.h +++ b/include/d/d_sc_game.h @@ -203,7 +203,7 @@ public: sReloaderType = type; } - static dCamera_c *getCamera(s32 idx); + static dCamera_c *getCamera(s32 idx = 0); static void setCamera(s32 idx, dCamera_c *); bool isFaderSettled() const { diff --git a/include/d/t/d_t_spore.h b/include/d/t/d_t_spore.h index 492aa9f0..e24375e3 100644 --- a/include/d/t/d_t_spore.h +++ b/include/d/t/d_t_spore.h @@ -1,19 +1,62 @@ #ifndef D_T_SPORE_H #define D_T_SPORE_H -#include "d/a/d_a_base.h" +#include "d/t/d_tg.h" +#include "egg/egg_types.h" +#include "m/m3d/m_proc.h" +#include "m/m_angle.h" +#include "m/m_vec.h" #include "s/s_State.hpp" -#include "s/s_StateMgr.hpp" -class dSporeTag_c : public dAcBase_c { +class dSporeProc_c : public m3d::proc_c { +public: + dSporeProc_c() : mpTexture(nullptr), field_0x39EC(false), field_0x39ED(false), field_0x39EE(0), field_0x39F0(0) {} + ~dSporeProc_c() {}; + + virtual void drawXlu() override; + + void execute(); + +private: + /* 0x0018 */ mVec3_c mSporesPos[400]; + /* 0x12D8 */ f32 field_0x12D8[400]; + /* 0x1918 */ f32 field_0x1918[400]; + /* 0x1F58 */ f32 field_0x1F58[400]; + /* 0x2598 */ f32 field_0x2598[400]; + /* 0x2BD8 */ f32 field_0x2BD8[400]; + /* 0x3218 */ mAng field_0x3218[400]; + /* 0x3538 */ mAng field_0x3538[400]; + /* 0x3858 */ s8 field_0x3858[400]; + /* 0x39E8 */ EGG::ResTIMG *mpTexture; + /* 0x39EC */ bool field_0x39EC; + /* 0x39ED */ u8 field_0x39ED; + /* 0x39EE */ s16 field_0x39EE; + /* 0x39F0 */ u8 field_0x39F0; + /* 0x39F1 */ u8 _0x39F1[0x3A02 - 0x39F1]; + /* 0x3A02 */ s16 field_0x3A02; + /* 0x3A04 */ s16 field_0x3A04; + /* 0x3A06 */ s16 field_0x3A06; + + friend class dSporeTag_c; +}; + +class dSporeTag_c : public dTg_c { public: dSporeTag_c() : mStateMgr(*this, sStateID::null) {} virtual ~dSporeTag_c() {} + virtual int create() override; + virtual int doDelete() override; + virtual int draw() override; + virtual bool createHeap() override; + virtual int actorExecute() override; + virtual int actorExecuteInEvent() override; + STATE_FUNC_DECLARE(dSporeTag_c, Wait); private: - /* 0x??? */ STATE_MGR_DECLARE(dSporeTag_c); + /* 0x0FC */ STATE_MGR_DECLARE(dSporeTag_c); + /* 0x138 */ dSporeProc_c mProc; }; #endif diff --git a/src/REL/d/t/d_t_spore.cpp b/src/REL/d/t/d_t_spore.cpp index 24a4dff2..aa7937eb 100644 --- a/src/REL/d/t/d_t_spore.cpp +++ b/src/REL/d/t/d_t_spore.cpp @@ -1,9 +1,269 @@ #include "d/t/d_t_spore.h" +#include "c/c_math.h" +#include "common.h" +#include "d/a/d_a_player.h" +#include "d/a/obj/d_a_obj_base.h" +#include "d/d_camera.h" +#include "d/d_light_env.h" +#include "d/d_sc_game.h" +#include "d/t/d_t_siren.h" +#include "egg/egg_types.h" +#include "egg/gfx/eggDrawGX.h" +#include "f/f_base.h" +#include "m/m_angle.h" +#include "m/m_color.h" +#include "m/m_mtx.h" +#include "m/m_vec.h" +#include "nw4r/g3d/g3d_scnobj.h" +#include "rvl/GX/GXGeometry.h" +#include "rvl/GX/GXTev.h" +#include "rvl/GX/GXTransform.h" +#include "rvl/GX/GXTypes.h" +#include "rvl/MTX/mtxvec.h" +#include "s/s_Math.h" + SPECIAL_ACTOR_PROFILE(SPORE_TAG, dSporeTag_c, fProfile::SPORE_TAG, 0xD, 0, 388); STATE_DEFINE(dSporeTag_c, Wait); +bool dSporeTag_c::createHeap() { + u32 size = 0; + if (!mProc.create(&mAllocator, &size)) { + return true; + } + mProc.mpTexture = static_cast(dAcObjBase_c::getOarcFile("Common", "tex/WK2_Houshi.bti")); + return true; +} + +int dSporeTag_c::create() { + CREATE_ALLOCATOR(dSporeTag_c); + + mProc.setPriorityDraw(0, 142); + mProc.setOption(nw4r::g3d::ScnObj::OPTION_DISABLE_DRAW_OPA, true); + mStateMgr.changeState(StateID_Wait); + mProc.field_0x39ED = true; + + return SUCCEEDED; +} + +int dSporeTag_c::doDelete() { + return SUCCEEDED; +} + +int dSporeTag_c::actorExecuteInEvent() { + mStateMgr.executeState(); + return SUCCEEDED; +} + +int dSporeTag_c::actorExecute() { + mStateMgr.executeState(); + return SUCCEEDED; +} + +int dSporeTag_c::draw() { + mProc.entry(); + return SUCCEEDED; +} + +void dSporeProc_c::execute() { + // NONMATCHING + // I dont feel like it + mVec3_c _playerPos = dAcPy_c::GetLink()->mPosition; + dLightEnv_c &env = dLightEnv_c::GetInstance(); + dCamera_c *pCam = dScGame_c::getCamera(); + + mVec3_c camPos; + mVec3_c camTowards; + + camPos = pCam->getPositionMaybe(); + camTowards = pCam->getField_0x78() - camPos; + + if (pCam != nullptr && camTowards.normalizeRS()) { + mVec3_c v; + mVec3_c pos = camPos + camTowards * 1000.f; + if (!field_0x39EC) { + for (s32 i = 0; i < 400; ++i) { + mSporesPos[i].x = pos.x + cM::rndFX(1100.f); + mSporesPos[i].y = pos.y + cM::rndFX(1100.f); + mSporesPos[i].z = pos.z + cM::rndFX(1100.f); + + field_0x1F58[i] = 0.f; + field_0x1918[i] = 1.f; + + field_0x3218[i] = cM::rnd() * 65535.f; + field_0x3538[i] = cM::rnd() * 65535.f; + + field_0x3858[i] = 0; + + field_0x2598[i] = cM::rndF(45.f) + 90.f; + field_0x2BD8[i] = cM::rndF(360.f); + + field_0x12D8[i] = cM::rndF(0.9f) + 0.1f; + + field_0x3A02 += 200; + field_0x3A04 += 50; + field_0x3A06 += 400; + } + field_0x3A02 = 0; + field_0x3A04 = 0; + field_0x3A06 = 0; + field_0x39EC = true; + } + + f32 f0 = 1050.f; + f32 f1 = 13.f; + f32 end = -1e9f; + f32 f3 = 900.f; + f32 f4 = 100.f; + f32 f5 = 3.f; + + for (s32 i = 0; i < 400; ++i) { + mVec3_c playerPos = dAcPy_c::GetLink()->mPosition; + mVec3_c point; + env.sphere_to_cartesian(field_0x2598[i], field_0x2BD8[i], &point); + + switch (field_0x3858[i]) { + case 0: { + field_0x3858[i] = 2; + } break; + case 1: { + if (playerPos.distance(mSporesPos[i]) < 150.f || dTgSiren_c::isOutOfTime()) { + field_0x3858[i]++; + } else { + mSporesPos[i].y += cM::rndF(30.f); + } + } break; + case 2: { + sLib::addCalc(&field_0x1918[i], 1.f, 0.5f, 0.1f, 0.001f); + f32 sin = field_0x3218[i].sin(); + field_0x3218[i] += sin * 90.f + 10.f; + + if (dScGame_c::currentSpawnInfo.getTrial() == SpawnInfo::TRIAL) { + if (dTgSiren_c::isOutOfTime()) { + mSporesPos[i].y += field_0x12D8[i] * 16.f; + field_0x2598[i] += sin * (field_0x12D8[i] - 0.5f) * 48.f; + field_0x2BD8[i] += sin * (field_0x12D8[i] - 0.5f) * 48.f; + mSporesPos[i] += point * ((field_0x12D8[i] * 0.5f) * 32.f + 0.5f); + } else { + mSporesPos[i].y += field_0x12D8[i] * 1.5f; + field_0x2598[i] += sin * (field_0x12D8[i] - 0.5f) * 12.f; + field_0x2BD8[i] += sin * (field_0x12D8[i] - 0.5f) * 12.f; + mSporesPos[i] += point * (field_0x12D8[i] * 4.f); + } + } else { + mSporesPos[i].y += field_0x12D8[i] * -0.5f; + field_0x2598[i] += sin * (field_0x12D8[i] - 0.5f) * 14.f; + field_0x2BD8[i] += sin * (field_0x12D8[i] - 0.5f) * f1; + mSporesPos[i] += point * (field_0x12D8[i] * 5.f); + } + + f32 camY = pCam->getField_0x2A8(); + if (end != camY && mSporesPos[i].y < camY) { + mSporesPos[i].y = camY; + } + } break; + } + + v = mSporesPos[i]; + if (v.distance(pos) > 1050.f) { + mSporesPos[i].x = pos.x + cM::rndFX(1100.f); + mSporesPos[i].y = pos.y + cM::rndFX(1100.f); + mSporesPos[i].z = pos.z + cM::rndFX(1100.f); + } else if (v.distance(pos) > 1000.f) { + mVec3_c out; + env.get_vectle_calc(&v, &pos, &out); + mSporesPos[i].x = pos.x + out.x * 1000.f; + mSporesPos[i].y = pos.y + out.y * 1000.f; + mSporesPos[i].z = pos.z + out.z * 1000.f; + + if (!dTgSiren_c::isOutOfTime()) { + field_0x3858[i] = 0; + } + } + + v = mSporesPos[i]; + f32 minDist = nw4r::ut::Min(v.distance(pos) / 1000.f, 1.f); + + f32 sin = (1.f - minDist) * field_0x3538[i].sin(); + field_0x3538[i] += f4 + f3 * field_0x12D8[i]; + field_0x1F58[i] = sin; + if (sin < 0.f) { + field_0x1F58[i] = 0.f; + } + + field_0x1918[i] = f5 * v.distance(camPos) / 1000.f + 1.f; + } + } +} + +void dSporeProc_c::drawXlu() { + using namespace EGG; + + DrawGX::LoadTexture(mpTexture, GX_TEXMAP0); + mColor color0(0x78, 0xB4, 0xFF, 1); // #78B4FF + mColor color1(0x2D, 0x50, 0x41, 0xFF); // #2D5041FF + + Matrix34f matrix( + EGG::DrawGX::s_cameraMtx._00, EGG::DrawGX::s_cameraMtx._01, EGG::DrawGX::s_cameraMtx._02, + EGG::DrawGX::s_cameraMtx._03, EGG::DrawGX::s_cameraMtx._10, EGG::DrawGX::s_cameraMtx._11, + EGG::DrawGX::s_cameraMtx._12, EGG::DrawGX::s_cameraMtx._13, EGG::DrawGX::s_cameraMtx._20, + EGG::DrawGX::s_cameraMtx._21, EGG::DrawGX::s_cameraMtx._22, EGG::DrawGX::s_cameraMtx._23 + ); + + dCamera_c *pCam = dScGame_c::getCamera(); + mVec3_c pos = pCam->getPositionMaybe(); + + if (dTgSiren_c::isOutOfTime()) { + color0.r = 0xFF; + color0.g = 0xDB; + color0.b = 0xA5; + } + + GXSetCullMode(GX_CULL_NONE); + GXSetClipMode(GX_CLIP_DISABLE); + + f32 scaleMult = 12.f; + + DrawGX::BeginDrawQuad(DrawGX::COLORCHAN_1, DrawGX::ZMODE_2, DrawGX::BLEND_3, true, false); + GXSetTevColor(GX_TEVREG1, color1); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C1, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + + GXColor c = EGG::DrawGX::WHITE; + s16 zRot; + s32 i; + mVec3_c *sporePos = mSporesPos; + for (i = 0, zRot = 0; i < 400; i++, zRot += 10) { + mVec3_c b; + mVec3_c a = mSporesPos[i]; + MTXMultVec(*matrix, a, b); + + mMtx_c m; + m.transS(b); + + color0.a = field_0x1F58[i] * 255.f; + if (color0.a != 0) { + m.ZrotM(field_0x3A02 + zRot); + + mMtx_c scale; + f32 scaleX = field_0x1918[i] * scaleMult * field_0x1F58[i]; + scale.scaleS(scaleX, scaleX, 1.f); + + m += scale; + GXSetTevColor(GX_TEVREG0, color0); + DrawGX::DrawDL(EGG::DrawGX::DL_13, m, c); + } + } + + GXSetClipMode(GX_CLIP_ENABLE); +} + void dSporeTag_c::initializeState_Wait() {} -void dSporeTag_c::executeState_Wait() {} +void dSporeTag_c::executeState_Wait() { + mProc.execute(); +} void dSporeTag_c::finalizeState_Wait() {}