From 6ff1da374122ae578683b48c1b0fa9a10c8a25d9 Mon Sep 17 00:00:00 2001 From: Mm2PL Date: Fri, 23 May 2025 02:28:56 +0200 Subject: [PATCH] d_a_jbo (#744) * Do initial work on d_a_jbo * Remove outdated comments * Move co_sph_src to be a function static variable * Mark as matching * Rename mParamsLower to mParam * Give names to mFramesUntilJump, mAnimRotation, mAnimationSpeed, mParticlePos * Give jbo_class::mState an enum * fixup! Give names to mFramesUntilJump, mAnimRotation, mAnimationSpeed, mParticlePos * Give resource ids an enum * Add documentation comment for actor * MWCC shenanigans * Rename variables to better match coding guidelines * Apply suggestions from code review - use J3DModel::setBaseScale() inline - use existing resource id enum - rename `i_actor` -> `i_this`, `that` -> `a_this` - use defines for missed returned booleans - replace `mDoAud_seStart` -> `fopAcM_seStart` Co-Authored-By: LagoLunatic * Apply rest of inlines i must have forgotten about them earlier --------- Co-authored-by: LagoLunatic --- configure.py | 2 +- include/d/actor/d_a_jbo.h | 37 +++++- src/d/actor/d_a_jbo.cpp | 236 +++++++++++++++++++++++++++++++++++--- 3 files changed, 253 insertions(+), 22 deletions(-) diff --git a/configure.py b/configure.py index a6c21c7d4..a44d536ba 100755 --- a/configure.py +++ b/configure.py @@ -1362,7 +1362,7 @@ config.libs = [ ActorRel(MatchingFor("GZLJ01", "GZLE01", "GZLP01"), "d_a_hitobj", extra_cflags=['-pragma "nosyminline on"']), ActorRel(MatchingFor("GZLJ01", "GZLE01", "GZLP01"), "d_a_hot_floor", extra_cflags=['-pragma "nosyminline on"']), ActorRel(MatchingFor("GZLJ01", "GZLE01", "GZLP01"), "d_a_ikari"), - ActorRel(NonMatching, "d_a_jbo"), + ActorRel(MatchingFor("GZLJ01", "GZLE01", "GZLP01"), "d_a_jbo", extra_cflags=['-pragma "nosyminline on"']), ActorRel(MatchingFor("GZLJ01", "GZLE01", "GZLP01"), "d_a_kaji"), ActorRel(NonMatching, "d_a_kanban"), ActorRel(NonMatching, "d_a_ki"), diff --git a/include/d/actor/d_a_jbo.h b/include/d/actor/d_a_jbo.h index 942c47cc1..7ef51ff20 100644 --- a/include/d/actor/d_a_jbo.h +++ b/include/d/actor/d_a_jbo.h @@ -1,13 +1,44 @@ #ifndef D_A_JBO_H #define D_A_JBO_H +#pragma push +#pragma sym off +#include "d/d_cc_d.h" +#pragma pop #include "f_op/f_op_actor.h" +class mDoExt_McaMorf; + +/** + * Baba bulb + * Only the lowest byte of fopAc_ac_c::base::mParameters is used, + * It is expected to be: + * - 0 - silently appears + * - 1 - plays a popup sound and animation on spawn + * - 2 - sets otherwise locally unused m2BA=1 + * - 3 - waits until an event bit is set, does nothing until then, after converts to 0 + * - 0xFF - converts to 0 + */ class jbo_class : public fopAc_ac_c { public: - /* 0x290 */ u8 m290[0x2BE - 0x290]; - /* 0x2BE */ s16 m2BE; - /* 0x2C0 */ u8 m2C0[0x438 - 0x2C0]; + /* 0x290 */ u8 m290[0x2AC - 0x290]; + /* 0x2AC */ request_of_phase_process_class mPhs; + /* 0x2B4 */ mDoExt_McaMorf* mpMorf; + + /* 0x2B8 */ u8 mParam; + /* 0x2B9 */ u8 m2B9[0x2B9 - 0x2B8]; + // FIXME: give following two fields names if external use is spotted + /* 0x2BA */ u8 m2BA; + /* 0x2BB */ u8 m2BB; + /* 0x2BC */ u8 mState; + /* 0x2BE */ s16 mFramesUntilJump; + /* 0x2C0 */ s16 mAnimRotation; + /* 0x2C2 */ s16 mAnimationSpeed; + /* 0x2C4 */ cXyz mParticlePos; + /* 0x2D0 */ dCcD_Stts mStts; + /* 0x30C */ dCcD_Sph mSph; }; +STATIC_ASSERT(sizeof(jbo_class) == 0x438); + #endif /* D_A_JBO_H */ diff --git a/src/d/actor/d_a_jbo.cpp b/src/d/actor/d_a_jbo.cpp index 6e2e0b0fd..62b7bdc62 100644 --- a/src/d/actor/d_a_jbo.cpp +++ b/src/d/actor/d_a_jbo.cpp @@ -4,55 +4,255 @@ // #include "d/actor/d_a_jbo.h" -#include "m_Do/m_Do_ext.h" +#include "d/actor/d_a_player.h" +#include "d/d_com_inf_game.h" +#include "d/d_kankyo.h" +#include "d/d_s_play.h" #include "d/d_procname.h" +#include "d/res/res_jbo.h" +#include "f_op/f_op_actor_mng.h" #include "d/d_priority.h" /* 00000078-00000108 .text nodeCallBack__FP7J3DNodei */ -static BOOL nodeCallBack(J3DNode*, int) { - /* Nonmatching */ +static BOOL nodeCallBack(J3DNode *i_node, int i_calcTiming) { + if (i_calcTiming == J3DNodeCBCalcTiming_In) { + J3DJoint* joint = reinterpret_cast(i_node); + s32 jntNo = joint->getJntNo(); + jbo_class* jbo = reinterpret_cast(j3dSys.getModel()->getUserArea()); + if (jbo != NULL && jntNo == 9) { + MTXCopy(j3dSys.getModel()->getAnmMtx(jntNo), *calc_mtx); + cXyz pos; + pos.x = 0; + pos.y = 0; + pos.z = 0; + MtxPosition(&pos, &jbo->mParticlePos); + } + } + return TRUE; } /* 00000108-00000240 .text jbo_draw_SUB__FP9jbo_class */ -void jbo_draw_SUB(jbo_class*) { - /* Nonmatching */ +void jbo_draw_SUB(jbo_class *i_this) { + J3DModel *model = i_this->mpMorf->mpModel; + model->setBaseScale(i_this->scale); + mDoMtx_stack_c::transS(i_this->current.pos.x, i_this->current.pos.y, i_this->current.pos.z); + mDoMtx_stack_c::YrotM(i_this->shape_angle.y); + mDoMtx_stack_c::XrotM(i_this->shape_angle.x); + mDoMtx_stack_c::ZrotM(i_this->shape_angle.z); + if (i_this->mAnimationSpeed) { + cXyz scale; + scale.x = REG8_F(1) + 1.1F; + scale.y = REG8_F(2) + 1.0F; + scale.z = REG8_F(3) + 0.9F; + i_this->mAnimRotation += i_this->mAnimationSpeed; + mDoMtx_stack_c::YrotM(i_this->mAnimRotation); + mDoMtx_stack_c::scaleM(scale); + mDoMtx_stack_c::YrotM(-i_this->mAnimRotation); + } + MTXCopy(mDoMtx_stack_c::now, model->getBaseTRMtx()); } /* 00000240-000002C4 .text daJBO_Draw__FP9jbo_class */ -static BOOL daJBO_Draw(jbo_class*) { - /* Nonmatching */ +static BOOL daJBO_Draw(jbo_class *i_this) { + J3DModel *model = i_this->mpMorf->getModel(); + if (i_this->mParam == 3) + return TRUE; + g_env_light.settingTevStruct(TEV_TYPE_ACTOR, &i_this->current.pos, &i_this->tevStr); + g_env_light.setLightTevColorType(model, &i_this->tevStr); + i_this->mpMorf->updateDL(); + return TRUE; } +// time from link entering blub to being vomited out +#define JUMP_ANIMATION_TIME 70 + +enum daJbo_State { + daJbo_State_IDLE = 0, + daJbo_State_WAIT_JUMP = 1, + daJbo_State_SPAWN = 2, +}; + /* 000002C4-00000584 .text jbo_move__FP9jbo_class */ -void jbo_move(jbo_class*) { - /* Nonmatching */ +void jbo_move(jbo_class *i_this) { + u8 state = i_this->mState; + switch (state) { + case daJbo_State_IDLE: { + if (dComIfGp_checkPlayerStatus0(0, daPyStts0_UNK80_e) && i_this->mSph.ChkCoHit()) { + J3DAnmTransform* anm = (J3DAnmTransform*)dComIfG_getObjectRes("JBO", JBO_BCK_IN1); + i_this->mpMorf->setAnm(anm, J3DFrameCtrl::EMode_NONE, 0.0, 1.0, 0.0, -1.0, NULL); + fopAcM_seStart(i_this, JA_SE_OBJ_JFLOWER_IN, 0); + dComIfGp_setItemMagicCount(4); + i_this->mFramesUntilJump = JUMP_ANIMATION_TIME; + i_this->mState += 1; + } + break; + } + case daJbo_State_WAIT_JUMP: { + i_this->mAnimationSpeed = JUMP_ANIMATION_TIME - i_this->mFramesUntilJump; + i_this->mAnimationSpeed *= 200; + if (i_this->mFramesUntilJump == 1) { + ((daPy_py_c *)dComIfGp_getPlayer(0))->onForceVomitJump(); + } + if (dComIfGp_checkPlayerStatus0(0, daPyStts0_UNK80000000_e)) { + J3DAnmTransform* anm = (J3DAnmTransform*)dComIfG_getObjectRes("JBO", JBO_BCK_OUT1); + i_this->mpMorf->setAnm(anm, J3DFrameCtrl::EMode_NONE, 0.0, 1.0, 0.0, -1.0, NULL); + fopAcM_seStart(i_this, JA_SE_OBJ_JFLOWER_OUT, 0); + i_this->mAnimationSpeed = 0; + i_this->mAnimRotation = 0; + JPABaseEmitter *emitter = dComIfGp_particle_setToon(0xa110, &i_this->mParticlePos); + if (emitter != NULL) { + emitter->setGlobalAlpha(100); + } + if (i_this->mParam == 2) { + i_this->m2BA = 1; + } + i_this->mState = daJbo_State_IDLE; + } + break; + } + case daJbo_State_SPAWN: { + if (i_this->mpMorf->isStop()) { + i_this->mState = daJbo_State_IDLE; + } + break; + } + } } /* 00000584-00000698 .text daJBO_Execute__FP9jbo_class */ -static BOOL daJBO_Execute(jbo_class*) { - /* Nonmatching */ +static BOOL daJBO_Execute(jbo_class* i_this) { + if (i_this->mParam == 3) { + if (dComIfGs_isEventBit(0x1801)) { + i_this->mParam = 0; + i_this->mSph.OnCoSPrmBit(cCcD_CoSPrm_Set_e); + } + return TRUE; + } + if (i_this->mFramesUntilJump != 0) { + i_this->mFramesUntilJump--; + } + switch(i_this->m2BB) { + case 0: + jbo_move(i_this); + break; + } + i_this->mpMorf->play(NULL, 0, 0); + cXyz pos(i_this->current.pos); + pos.y += 30.0; + i_this->mSph.SetC(pos); + i_this->mSph.SetR(55.0); + dComIfG_Ccsp()->Set(&i_this->mSph); + jbo_draw_SUB(i_this); + return TRUE; } /* 00000698-000006A0 .text daJBO_IsDelete__FP9jbo_class */ static BOOL daJBO_IsDelete(jbo_class*) { - /* Nonmatching */ + return true; } /* 000006A0-000006D0 .text daJBO_Delete__FP9jbo_class */ -static BOOL daJBO_Delete(jbo_class*) { - /* Nonmatching */ +static BOOL daJBO_Delete(jbo_class* i_this) { + dComIfG_resDelete(&i_this->mPhs, "JBO"); + return TRUE; } /* 000006D0-0000081C .text useHeapInit__FP10fopAc_ac_c */ -static BOOL useHeapInit(fopAc_ac_c*) { - /* Nonmatching */ +static BOOL useHeapInit(fopAc_ac_c* i_this) { + jbo_class* a_this = (jbo_class*)i_this; + mDoExt_McaMorf* morf = new mDoExt_McaMorf( + (J3DModelData *)dComIfG_getObjectRes("JBO", JBO_BMD_JH), + /*callback1=*/ NULL, + /*callback2=*/ NULL, + (J3DAnmTransformKey *)dComIfG_getObjectRes("JBO", JBO_BCK_IN1), + J3DFrameCtrl::EMode_RESET, + 0.0f, + 0, + -1, + 1, + /*basAnm=*/ NULL, + 0, + /*differedDlistFlag=*/ 0x11020203 + ); + a_this->mpMorf = morf; + if (a_this->mpMorf == NULL || a_this->mpMorf->mpModel == NULL) { + return FALSE; + } + a_this->mpMorf->getModel()->setUserArea(reinterpret_cast(a_this)); + for (u16 i = 0; i < a_this->mpMorf->getModel()->getModelData()->getJointNum(); i++) { + a_this->mpMorf->getModel()->getModelData()->getJointNodePointer(i)->setCallBack(nodeCallBack); + } + return TRUE; } /* 0000081C-00000A90 .text daJBO_Create__FP10fopAc_ac_c */ -static cPhs_State daJBO_Create(fopAc_ac_c*) { - /* Nonmatching */ +static cPhs_State daJBO_Create(fopAc_ac_c* i_this) { + fopAcM_SetupActor(i_this, jbo_class); + jbo_class* a_this = (jbo_class*)i_this; + cPhs_State state = dComIfG_resLoad(&a_this->mPhs, "JBO"); + if (state == cPhs_COMPLEATE_e) { + if (!fopAcM_entrySolidHeap(i_this, &useHeapInit, 0x1c20)) { + return cPhs_ERROR_e; + } else { + a_this->mParam = fopAcM_GetParam(a_this); + if (a_this->mParam == 0xFF) { + a_this->mParam = 0; + } + + if (REG8_S(9) != 0) { + a_this->mParam = REG8_S(9); + } + fopAcM_SetMtx(a_this, a_this->mpMorf->getModel()->getBaseTRMtx()); + a_this->attention_info.flags = 0; + a_this->mStts.Init(0xff, 0xff, a_this); + static dCcD_SrcSph co_sph_src = { + // dCcD_SrcGObjInf + { + /* Flags */ 0, + /* SrcObjAt Type */ 0, + /* SrcObjAt Atp */ 0, + /* SrcObjAt SPrm */ 0, + /* SrcObjTg Type */ 0, + /* SrcObjTg SPrm */ 0, + /* SrcObjCo SPrm */ cCcD_CoSPrm_VsEnemy_e|cCcD_CoSPrm_IsOther_e|cCcD_CoSPrm_Set_e, + /* 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, + }, + // cM3dGSphS + { + /* Center */ 0.0f, 0.0f, 0.0f, + /* Radius */ 15.0f, + }, + }; + a_this->mSph.Set(co_sph_src); + a_this->mSph.SetStts(&a_this->mStts); + if (a_this->mParam == 3) { + fopAcM_OffStatus(a_this, fopAcStts_SHOWMAP_e); + a_this->mSph.ClrCoSet(); + } + if (a_this->mParam == 1) { + J3DAnmTransform* pAnimRes = (J3DAnmTransform*) dComIfG_getObjectRes("JBO", JBO_BCK_UMARERU1); + a_this->mpMorf->setAnm(pAnimRes, J3DFrameCtrl::EMode_NONE, 0.0, 1.0, 0.0, -1.0, NULL); + fopAcM_seStart(a_this, JA_SE_CM_BV_BASE_POPUP, 0); + a_this->mState = daJbo_State_SPAWN; + } + a_this->gbaName = 0x21; + jbo_draw_SUB(a_this); + } + } + return state; } + static actor_method_class l_daJBO_Method = { (process_method_func)daJBO_Create, (process_method_func)daJBO_Delete,