From 5063d3433ca354f580f3689e2db6e7d606372093 Mon Sep 17 00:00:00 2001 From: Teddy Heidmann Date: Thu, 30 Jul 2026 19:46:56 -0700 Subject: zeldaret/tww#385 d_a_obj_drift (#1100) * zeldaret/tww#385 d_a_obj_drift * configure changes * GZLJ01 * D44J01 * Not matching D44J01 * demo support * variable cleanup * revert new helper * revert again * Attempt 2 * Try to fix non-deterministic issue * Revert tide fix * debug mapping * more map fixes * Update src/d/actor/d_a_obj_drift.cpp Co-authored-by: LagoLunatic * review comments --------- Co-authored-by: LagoLunatic --- configure.py | 2 +- include/d/actor/d_a_obj_drift.h | 52 +++++- src/d/actor/d_a_obj_drift.cpp | 369 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 396 insertions(+), 27 deletions(-) diff --git a/configure.py b/configure.py index 68c24a3c..3623fbaa 100755 --- a/configure.py +++ b/configure.py @@ -1720,7 +1720,7 @@ config.libs = [ ActorRel(Matching, "d_a_obj_correct"), ActorRel(Matching, "d_a_obj_dmgroom"), ActorRel(Matching, "d_a_obj_dragonhead"), - ActorRel(NonMatching, "d_a_obj_drift"), + ActorRel(Matching, "d_a_obj_drift"), ActorRel(Matching, "d_a_obj_eayogn"), ActorRel(Matching, "d_a_obj_ebomzo"), ActorRel(NonMatching, "d_a_obj_ekskz"), diff --git a/include/d/actor/d_a_obj_drift.h b/include/d/actor/d_a_obj_drift.h index 258de154..bd76c46d 100644 --- a/include/d/actor/d_a_obj_drift.h +++ b/include/d/actor/d_a_obj_drift.h @@ -1,14 +1,28 @@ #ifndef D_A_OBJ_DRIFT_H #define D_A_OBJ_DRIFT_H +#include "SSystem/SComponent/c_xyz.h" #include "d/d_bg_s_movebg_actor.h" +#include "dolphin/types.h" #include "f_op/f_op_actor.h" #include "d/d_bg_w.h" namespace daObjDrift { class Act_c : public dBgS_MoveBgActor { public: - void prm_get_type() const {} + enum Mode { + MODE_WAIT = 0x0, + MODE_ROT = 0x1, + }; + + enum Prm_e { + PRM_TYPE_W = 3, + PRM_TYPE_S = 0, + }; + + int prm_get_type() const { + return daObj::PrmAbstract(this, PRM_TYPE_W, PRM_TYPE_S); + } virtual BOOL CreateHeap(); virtual BOOL Create(); @@ -24,13 +38,45 @@ namespace daObjDrift { void mode_rot(); void set_mtx(); void init_mtx(); - void rideCB(dBgW*, fopAc_ac_c*, fopAc_ac_c*); + static void rideCB(dBgW*, fopAc_ac_c*, fopAc_ac_c*); void set_current(); virtual BOOL Execute(Mtx**); virtual BOOL Draw(); + + static const char M_arcname[]; + static const dCcD_SrcCyl M_cyl_src; public: - /* Place member variables here */ + /* 0x2C8 */ request_of_phase_process_class mPhase; + /* 0x2D0 */ J3DModel* mModel; + /* 0x2D4 */ dCcD_Stts mStts; + /* 0x310 */ dCcD_Cyl mCyl; + /* 0x440 */ int mType; + /* 0x444 */ Mtx mMtx; + /* 0x474 */ fpc_ProcID mFlowerPid; + /* 0x478 */ s32 mMode; + /* 0x47C */ f32 mRideYOff; + /* 0x480 */ f32 mTiltTargetZ; + /* 0x484 */ f32 mTiltTargetX; + /* 0x488 */ f32 mTiltVelZ; + /* 0x48C */ f32 mTiltVelX; + /* 0x490 */ f32 mTiltZ; + /* 0x494 */ f32 mTiltX; + /* 0x498 */ s16 mWavePhaseX; + /* 0x49A */ s16 mWavePhaseY; + /* 0x49C */ s16 mWavePhaseZ; + /* 0x49E */ bool mRideFlag; + /* 0x49F */ u8 field_0x49F; + /* 0x4A0 */ s16 mTargetAngleY; + /* 0x4A2 */ s16 mAngleChaseY; + /* 0x4A4 */ cXyz mHitDir; + /* 0x4B0 */ cXyz field_0x4B0; + /* 0x4BC */ cXyz mPrevPos; + /* 0x4C8 */ f32 field_0x4C8; + /* 0x4CC */ f32 field_0x4CC; + /* 0x4D0 */ f32 field_0x4D0; + /* 0x4D4 */ f32 field_0x4D4; + /* 0x4D8 */ f32 mRotTimer; }; }; diff --git a/src/d/actor/d_a_obj_drift.cpp b/src/d/actor/d_a_obj_drift.cpp index 92c9bc41..4e361f4c 100644 --- a/src/d/actor/d_a_obj_drift.cpp +++ b/src/d/actor/d_a_obj_drift.cpp @@ -5,95 +5,418 @@ #include "d/dolzel_rel.h" // IWYU pragma: keep #include "d/actor/d_a_obj_drift.h" +#include "d/actor/d_a_player.h" +#include "res/Object/Kryu.h" + +namespace daObjDrift { + namespace { + struct Attr_c { + /* 0x00 */ f32 mWaveHeight; + /* 0x04 */ f32 mWaveSpeed; + /* 0x08 */ f32 mWavePhase; + /* 0x0C */ f32 mWaveAmplitude; + /* 0x10 */ f32 mRideYOff; + /* 0x14 */ s16 mWavePhaseXStep; + /* 0x16 */ s16 field_0x16; + /* 0x18 */ f32 mWaveSinScale; + /* 0x1C */ f32 field_0x1C; + /* 0x20 */ f32 mTiltChaseWait; + /* 0x24 */ f32 mTiltChaseRot; + /* 0x28 */ f32 mPosMoveDamp; + /* 0x2C */ s16 mWavePhaseYStep; + /* 0x2E */ s16 mWavePhaseZStep; + /* 0x30 */ f32 mTiltSinScale; + /* 0x34 */ f32 field_0x34; + /* 0x38 */ s16 field_0x38; + /* 0x3A */ s16 field_0x3A; + /* 0x3C */ s16 mRotTimerMax; + /* 0x3E */ s16 field_0x3E; + }; + + static const Attr_c L_attr = { + /* mWaveHeight */ 500.0f, + /* mWaveSpeed */ 0.04f, + /* mWavePhase */ 0.01f, + /* mWaveAmplitude */ 0.02f, + /* mRideYOff */ -20.0f, + /* mWavePhaseXStep */ 400, + /* field_0x16 */ 0, + /* mWaveSinScale */ 0.3f, + /* field_0x1C */ 0.12f, + /* mTiltChaseWait */ 0.8f, + /* mTiltChaseRot */ 0.5f, + /* mPosMoveDamp */ 0.07f, + /* mWavePhaseYStep */ 1000, + /* mWavePhaseZStep */ 1111, + /* mTiltSinScale */ 0.01f, + /* field_0x34 */ 0.5f, + /* field_0x38 */ 30, + /* field_0x3A */ 30, + /* mRotTimerMax */ 10, + /* field_0x3E */ 0, + }; + + inline const Attr_c& attr() { return L_attr; } + } // namespace +} // namespace daObjDrift + +const char daObjDrift::Act_c::M_arcname[] = "Kryu"; /* 0x40 */ + +const dCcD_SrcCyl daObjDrift::Act_c::M_cyl_src = { /* 0x48 */ + { + /* Flags */ 0, + /* SrcObjAt Type */ 0, + /* SrcObjAt Atp */ 0, + /* SrcObjAt SPrm */ 0, + /* SrcObjTg Type */ AT_TYPE_WIND, + /* SrcObjTg SPrm */ cCcD_TgSPrm_Set_e | cCcD_TgSPrm_IsOther_e, + /* SrcObjCo SPrm */ 0, + /* SrcGObjAt Se */ 0, + /* SrcGObjAt HitMark */ 0, + /* SrcGObjAt Spl */ 0, + /* SrcGObjAt Mtrl */ 0, + /* SrcGObjAt SPrm */ 0, + /* SrcGObjTg Se */ 0, + /* SrcGObjTg HitMark */ 0, + /* SrcGObjTg Spl */ 0, + /* SrcGObjTg Mtrl */ 0, + /* SrcGObjTg SPrm */ 0, + /* SrcGObjCo SPrm */ 0, + }, + {{ + /* Center */ {0.0f, 0.0f, 0.0f}, + /* Radius */ 300.0f, + /* Height */ 600.0f, + }}, +}; /* 000000EC-000001A0 .text CreateHeap__Q210daObjDrift5Act_cFv */ BOOL daObjDrift::Act_c::CreateHeap() { - /* Nonmatching */ + J3DModelData* model_data = (J3DModelData*)dComIfG_getObjectRes(M_arcname, dRes_INDEX_KRYU_BDL_RYU_00_e); + JUT_ASSERT(0x13A, model_data != NULL); + mModel = mDoExt_J3DModel__create(model_data, 0x80000, 0x11000022); + return mModel != NULL; } /* 000001A0-00000370 .text Create__Q210daObjDrift5Act_cFv */ BOOL daObjDrift::Act_c::Create() { - /* Nonmatching */ + f32 L_waterY[2]; + fopAcM_SetMtx(this, mModel->getBaseTRMtx()); + init_mtx(); + + fopAcM_setCullSizeBox(this, -550.0f, -180.0f, -550.0f, 550.0f, 605.0f, 550.0f); + mStts.Init(0xFF, 0xFF, this); + mCyl.Set(M_cyl_src); + mCyl.SetStts(&mStts); + mCyl.SetTgVec((cXyz&)cXyz::Zero); + mCyl.OnTgNoHitMark(); + + make_flower(); + mpBgW->SetRideCallback(rideCB); + mode_wait_init(); + if (fopAcM_getWaterY(&home.pos, L_waterY)) { + eyePos.y = L_waterY[0]; + } + + mRideYOff = 0.0f; + mTiltTargetZ = 0.0f; + mTiltTargetX = 0.0f; + mTiltVelZ = 0.0f; + mTiltVelX = 0.0f; + mTiltZ = 0.0f; + mTiltX = 0.0f; + + mWavePhaseX = cM_rndFX(32768.0f); + mWavePhaseY = cM_rndFX(32768.0f); + mWavePhaseZ = cM_rndFX(32768.0f); + mRideFlag = FALSE; + + mTargetAngleY = 0; + mAngleChaseY = 0; + + mHitDir.set((cXyz&)cXyz::Zero); + field_0x4B0.setall(5.0f); + mPrevPos.set(current.pos); + f32 prevY = mPrevPos.y; + field_0x4C8 = prevY; + field_0x4CC = prevY; + + // f32 endZero = 0.0f; + field_0x4D0 = 0.0f; + field_0x4D4 = 0.0f; + + return TRUE; } /* 00000370-0000050C .text Mthd_Create__Q210daObjDrift5Act_cFv */ cPhs_State daObjDrift::Act_c::Mthd_Create() { - /* Nonmatching */ + fopAcM_ct(this, Act_c); + + cPhs_State phase_state = dComIfG_resLoad(&mPhase, M_arcname); + if (phase_state == cPhs_COMPLEATE_e) { + mType = prm_get_type(); + + phase_state = MoveBGCreate( + M_arcname, + dRes_INDEX_KRYU_DZB_RYU_00_e, + dBgS_MoveBGProc_TypicalRotY, + DEMO_SELECT(0x8000, 0x1B80) + ); + JUT_ASSERT(0x19B, (phase_state == cPhs_COMPLEATE_e) || (phase_state == cPhs_ERROR_e)); + } + return phase_state; } /* 0000075C-000007EC .text make_flower__Q210daObjDrift5Act_cFv */ void daObjDrift::Act_c::make_flower() { - /* Nonmatching */ + if (mType >= 0 && mType <= 1) { + cXyz pos; + csXyz angle; + calc_flower_param(&pos, &angle); + static const s16 pf_name[2] = {fpcNm_JBO_e, fpcNm_BO_e}; + mFlowerPid = fopAcM_create( + pf_name[mType], + 0, + &pos, + fopAcM_GetHomeRoomNo(this), + &angle, + NULL, + -1, + NULL); + } else { + mFlowerPid = fpcM_ERROR_PROCESS_ID_e; + } } /* 000007EC-00000890 .text calc_flower_param__Q210daObjDrift5Act_cFP4cXyzP5csXyz */ -void daObjDrift::Act_c::calc_flower_param(cXyz*, csXyz*) { - /* Nonmatching */ +void daObjDrift::Act_c::calc_flower_param(cXyz* i_pos, csXyz* i_angle) { + static cXyz offset_vec(-489.35f, 600.0f, 0.0f); + + mDoMtx_multVec(mMtx, &offset_vec, i_pos); + mDoMtx_MtxToRot(mMtx, i_angle); } /* 00000890-00000954 .text set_flower_current__Q210daObjDrift5Act_cFv */ void daObjDrift::Act_c::set_flower_current() { - /* Nonmatching */ + if (mFlowerPid == fpcM_ERROR_PROCESS_ID_e) { + return; + } + + fopAc_ac_c* flower = fopAcM_SearchByID(mFlowerPid); + if (flower != NULL) { + cXyz pos; + csXyz angle; + calc_flower_param(&pos, &angle); + flower->current.pos = pos; + if (mType == 0) { + flower->shape_angle = angle; + } else { + flower->current.angle = angle; + } + } } /* 00000954-0000095C .text Delete__Q210daObjDrift5Act_cFv */ BOOL daObjDrift::Act_c::Delete() { - /* Nonmatching */ + return TRUE; } /* 0000095C-000009A8 .text Mthd_Delete__Q210daObjDrift5Act_cFv */ BOOL daObjDrift::Act_c::Mthd_Delete() { - /* Nonmatching */ + s32 ret = MoveBGDelete(); + dComIfG_resDeleteDemo(&mPhase, M_arcname); + return ret; } /* 000009A8-000009C0 .text mode_wait_init__Q210daObjDrift5Act_cFv */ void daObjDrift::Act_c::mode_wait_init() { - /* Nonmatching */ + fopAcM_OnStatus(this, fopAcStts_NOCULLEXEC_e); + mMode = MODE_WAIT; } /* 000009C0-00000A80 .text mode_wait__Q210daObjDrift5Act_cFv */ void daObjDrift::Act_c::mode_wait() { - /* Nonmatching */ + if (mCyl.ChkTgHit()) { + mCyl.ClrTgHit(); + if (fopAcM_searchPlayerDistanceXZ2(this) > 302500.0f) { + cXyz* l_tgrVec = mCyl.GetTgRVecP(); + mHitDir.set(*l_tgrVec); + mHitDir.normalizeZP(); + mode_rot_init(); + } + } else { + mCyl.MoveCAtTg(current.pos); + dComIfG_Ccsp()->Set(&mCyl); + } } /* 00000A80-00000B38 .text mode_rot_init__Q210daObjDrift5Act_cFv */ void daObjDrift::Act_c::mode_rot_init() { - /* Nonmatching */ + fopAcM_OffStatus(this, fopAcStts_NOCULLEXEC_e); + mTargetAngleY = shape_angle.y + 0x8000; + mAngleChaseY = 0; + shape_angle.y += 10; + mRotTimer = 0.0f; + mMode = MODE_ROT; + fopAcM_seStart(this, JA_SE_OBJ_RYUBOKU_MOVE, 0); } /* 00000B38-00000C3C .text mode_rot__Q210daObjDrift5Act_cFv */ void daObjDrift::Act_c::mode_rot() { - /* Nonmatching */ + s16 yDiff = mTargetAngleY - shape_angle.y; + if (yDiff <= 0) { + shape_angle.y = mTargetAngleY; + mHitDir.set(cXyz::Zero); + mode_wait_init(); + } else { + if (yDiff < 0x2000) { + cLib_chaseS(&mAngleChaseY, 0x14, 0xA); + } else { + cLib_chaseS(&mAngleChaseY, 0x190, 0x14); + } + shape_angle.y += mAngleChaseY; + } + + if (mRotTimer >= attr().mRotTimerMax) { + mRotTimer = 0.0f; + field_0x4D0 = 1.0f; + } else { + mRotTimer += 1.0f; + } } /* 00000C3C-00000D18 .text set_mtx__Q210daObjDrift5Act_cFv */ void daObjDrift::Act_c::set_mtx() { - /* Nonmatching */ + mDoMtx_stack_c::transS(current.pos); + Quaternion quat; + cXyz axis(mTiltX, 1.0f, mTiltZ); + daObj::quat_rotBaseY2(&quat, axis); + mDoMtx_stack_c::quatM(&quat); + mDoMtx_stack_c::ZXYrotM(shape_angle); + mModel->setBaseTRMtx(mDoMtx_stack_c::get()); + cMtx_copy(mDoMtx_stack_c::get(), mMtx); + field_0x4CC = field_0x4C8; + field_0x4C8 = mPrevPos.y; + mDoMtx_multVecZero(mDoMtx_stack_c::get(), &mPrevPos); } /* 00000D18-00000D54 .text init_mtx__Q210daObjDrift5Act_cFv */ void daObjDrift::Act_c::init_mtx() { - /* Nonmatching */ + mModel->setBaseScale(scale); + set_mtx(); } /* 00000D54-00000EC4 .text rideCB__Q210daObjDrift5Act_cFP4dBgWP10fopAc_ac_cP10fopAc_ac_c */ -void daObjDrift::Act_c::rideCB(dBgW*, fopAc_ac_c*, fopAc_ac_c*) { - /* Nonmatching */ +void daObjDrift::Act_c::rideCB(dBgW*, fopAc_ac_c* i_this, fopAc_ac_c* i_ride) { + Act_c* drift = (Act_c*)i_this; + daPy_py_c* player = (daPy_py_c*)i_ride; + if (fopAcM_GetProfName(player) != fpcNm_PLAYER_e) { + return; + } + f32 ratio = 1.0f / attr().mWaveHeight; + drift->mRideYOff = attr().mRideYOff; + + cXyz delta; + cXyz localDelta; + Mtx invMtx; + delta = player->current.pos - drift->current.pos; + if (PSMTXInverse(drift->mMtx, invMtx) && + !dComIfGp_checkPlayerStatus0(0, daPyStts0_HANG_e)) { + mDoMtx_multVecSR(invMtx, &delta, &localDelta); + f32 sqMag = localDelta.abs2XZ(); + if (localDelta.y < 400.0f) { + if (sqMag < 129600.0f) { + drift->mRideFlag = TRUE; + } + } else if (localDelta.y < 550.0f) { + if (sqMag < 48400.0f) { + drift->mRideFlag = TRUE; + } + } + } else { + drift->mRideFlag = TRUE; + } + if (drift->mRideFlag == FALSE) { + drift->mTiltTargetZ = delta.z * (ratio * attr().field_0x1C); + drift->mTiltTargetX = delta.x * (ratio * attr().field_0x1C); + } } /* 00000EC4-00001104 .text set_current__Q210daObjDrift5Act_cFv */ void daObjDrift::Act_c::set_current() { - /* Nonmatching */ + f32 y = mRideYOff + home.pos.y; + mWavePhaseX += attr().mWavePhaseXStep; + f32 sinVal = cM_ssin(mWavePhaseX); + f32 yDelta = y - current.pos.y; + gravity = yDelta * attr().mWaveAmplitude + + sinVal * attr().mWaveSinScale; + daObj::posMoveF_stream(this, NULL, &cXyz::Zero, attr().mWaveSpeed, attr().mWavePhase); +#if VERSION == VERSION_DEMO + f32 rotFactor; + f32 chaseFactor; +#else + f32 chaseFactor; + f32 rotFactor; +#endif + if (mRideFlag != 0) { + rotFactor = 0.2f; + } else { + rotFactor = 1.0f; + } + if (mMode == MODE_ROT) { + chaseFactor = attr().mTiltChaseRot; + } else { + chaseFactor = attr().mTiltChaseWait; + } + mHitDir *= 0.95f; + mWavePhaseY += attr().mWavePhaseYStep; + mWavePhaseZ += attr().mWavePhaseZStep; + f32 diffZ = mTiltZ - mTiltTargetZ; + f32 diffX = mTiltX - mTiltTargetX; + f32 sinY = cM_ssin(mWavePhaseY); + f32 z_val = mHitDir.z * attr().field_0x34 + + (rotFactor * (sinY * attr().mTiltSinScale) + - diffZ * chaseFactor); + f32 sinZ = cM_ssin(mWavePhaseZ); + f32 x_val = mHitDir.x * attr().field_0x34 + + (rotFactor * (sinZ * attr().mTiltSinScale) + - diffX * chaseFactor); + mTiltVelZ += z_val; + mTiltVelX += x_val; + mTiltVelZ *= attr().mPosMoveDamp; + mTiltVelX *= attr().mPosMoveDamp; + mTiltZ += mTiltVelZ; + mTiltX += mTiltVelX; + mRideYOff = 0.0f; + mTiltTargetZ = 0.0f; + mTiltTargetX = 0.0f; + mRideFlag = FALSE; } /* 00001104-000011D0 .text Execute__Q210daObjDrift5Act_cFPPA3_A4_f */ -BOOL daObjDrift::Act_c::Execute(Mtx**) { - /* Nonmatching */ +BOOL daObjDrift::Act_c::Execute(Mtx** mtx) { + typedef void (daObjDrift::Act_c::*procFunc)(); + static procFunc mode_proc[] = { + &daObjDrift::Act_c::mode_wait, + &daObjDrift::Act_c::mode_rot, + }; + (this->*mode_proc[mMode])(); + + set_current(); + set_mtx(); + *mtx = &mMtx; + set_flower_current(); + return TRUE; } /* 000011D0-00001270 .text Draw__Q210daObjDrift5Act_cFv */ BOOL daObjDrift::Act_c::Draw() { - /* Nonmatching */ + g_env_light.settingTevStruct(TEV_TYPE_BG0, ¤t.pos, &tevStr); + g_env_light.setLightTevColorType(mModel, &tevStr); + dComIfGd_setListBG(); + mDoExt_modelUpdateDL(mModel); + dComIfGd_setList(); + return TRUE; } namespace daObjDrift { @@ -115,12 +438,12 @@ BOOL Mthd_Execute(void* i_this) { /* 000012D0-000012FC .text Mthd_Draw__Q210daObjDrift27@unnamed@d_a_obj_drift_cpp@FPv */ BOOL Mthd_Draw(void* i_this) { - return ((daObjDrift::Act_c*)i_this)->Draw(); + return ((daObjDrift::Act_c*)i_this)->MoveBGDraw(); } /* 000012FC-00001328 .text Mthd_IsDelete__Q210daObjDrift27@unnamed@d_a_obj_drift_cpp@FPv */ BOOL Mthd_IsDelete(void* i_this) { - return ((daObjDrift::Act_c*)i_this)->IsDelete(); + return ((daObjDrift::Act_c*)i_this)->MoveBGIsDelete(); } static actor_method_class Mthd_Table = { -- cgit v1.2.3