diff --git a/configure.py b/configure.py index 41d6373d0..9134b1555 100644 --- a/configure.py +++ b/configure.py @@ -427,7 +427,7 @@ config.libs = [ Object(NonMatching, "d/actor/d_a_grid.cpp"), Object(NonMatching, "d/actor/d_a_himo2.cpp"), Object(NonMatching, "d/actor/d_a_hookshot.cpp"), - Object(NonMatching, "d/actor/d_a_ib.cpp"), + Object(Matching, "d/actor/d_a_ib.cpp", extra_cflags=['-pragma "nosyminline on"']), Object(NonMatching, "d/actor/d_a_item.cpp"), Object(Matching, "d/actor/d_a_itembase.cpp"), Object(Matching, "d/actor/d_a_nh.cpp"), diff --git a/include/JSystem/J3DGraphAnimator/J3DAnimation.h b/include/JSystem/J3DGraphAnimator/J3DAnimation.h index 65ca8d10a..b3cd804de 100644 --- a/include/JSystem/J3DGraphAnimator/J3DAnimation.h +++ b/include/JSystem/J3DGraphAnimator/J3DAnimation.h @@ -630,6 +630,11 @@ public: LOOP_MIRROR_REPEAT_e, }; + enum State_e { + STATE_STOP_E = 0x1, + STATE_LOOP_E = 0x2, + }; + J3DFrameCtrl() { this->init(0); } void init(s16 end); BOOL checkPass(f32); diff --git a/include/SSystem/SComponent/c_cc_d.h b/include/SSystem/SComponent/c_cc_d.h index fb847b490..2a5214568 100644 --- a/include/SSystem/SComponent/c_cc_d.h +++ b/include/SSystem/SComponent/c_cc_d.h @@ -34,6 +34,7 @@ enum cCcD_ObjAtType { /* 0x00001000 */ AT_TYPE_UNK1000 = (1 << 12), /* 0x00002000 */ AT_TYPE_UNK2000 = (1 << 13), /* 0x00004000 */ AT_TYPE_NORMAL_ARROW = (1 << 14), + /* 0x00008000 */ AT_TYPE_UNK8000 = (1 << 15), /* 0x00010000 */ AT_TYPE_SKULL_HAMMER = (1 << 16), /* 0x00020000 */ AT_TYPE_UNK20000 = (1 << 17), /* 0x00040000 */ AT_TYPE_FIRE_ARROW = (1 << 18), @@ -43,6 +44,7 @@ enum cCcD_ObjAtType { /* 0x00400000 */ AT_TYPE_UNK400000 = (1 << 22), /* 0x00800000 */ AT_TYPE_LIGHT = (1 << 23), /* 0x01000000 */ AT_TYPE_STALFOS_MACE = (1 << 24), + /* 0x02000000 */ AT_TYPE_UNK2000000 = (1 << 25), /* 0x04000000 */ AT_TYPE_DARKNUT_SWORD = (1 << 26), /* 0x08000000 */ AT_TYPE_GRAPPLING_HOOK = (1 << 27), /* 0x10000000 */ AT_TYPE_MOBLIN_SPEAR = (1 << 28), diff --git a/include/d/actor/d_a_ib.h b/include/d/actor/d_a_ib.h new file mode 100644 index 000000000..571b9848e --- /dev/null +++ b/include/d/actor/d_a_ib.h @@ -0,0 +1,75 @@ +#ifndef D_A_IB_H +#define D_A_IB_H + +#include "f_op/f_op_actor_mng.h" +#include "d/d_bg_s_acch.h" +#include "d/d_cc_d.h" +#include "m_Do/m_Do_ext.h" +#include "d/d_particle.h" + +class daIball_c : public fopAc_ac_c { +public: + enum Mode { + MODE_WAIT = 0x0, + MODE_WATER = 0x1, + }; + + typedef void (daIball_c::*ModeFunc)(); + + void setPointLight(); + void createDisappearEffect(int, int); + BOOL createItem(); + BOOL dead(); + void checkGeo(); + void mode_wait_init(); + void mode_wait(); + void mode_water_init(); + void mode_water(); + void animControl(); + void damage(); + void set_mtx(); + void CreateInit(); + BOOL _daIball_draw(); + BOOL _daIball_execute(); + BOOL _daIball_delete(); + s32 _daIball_create(); + BOOL CreateHeap(); + + static void init(); + static void regist(fopAc_ac_c*); + static void remove(fopAc_ac_c*); + static void remove_old(); + + static u32 m_ib_actor[5]; + + static char m_arcname[]; + static dCcD_SrcCyl m_cyl_src; + +public: + /* 0x290 */ dBgS_ObjAcch mAcch; + /* 0x454 */ dBgS_AcchCir mAcchCir; + /* 0x494 */ dCcD_Stts mStts; + /* 0x4D0 */ dCcD_Cyl mCyl; + /* 0x600 */ J3DModel* mpModel; + /* 0x604 */ mDoExt_btkAnm mBtkAnm; + /* 0x618 */ mDoExt_brkAnm mBrkAnm[2]; + /* 0x648 */ mDoExt_bckAnm mBckAnm; + /* 0x658 */ dPa_rippleEcallBack mRippleCb; + /* 0x66C */ int mTimer; + /* 0x670 */ u8 m670[0x674 - 0x670]; + /* 0x674 */ int mPlaySpeedIdx; + /* 0x678 */ u8 m678[0x67C - 0x678]; + /* 0x67C */ f32 mPrevSpeedY; + /* 0x680 */ u8 mMode; + /* 0x681 */ bool mbPlayedSe; + /* 0x682 */ u8 m682[0x684 - 0x682]; + /* 0x684 */ LIGHT_INFLUENCE mLight; + /* 0x6A4 */ f32 mLightFlickerMult; +}; + +namespace daIball_prm { + inline s8 getItemBitNo(daIball_c* ib) { return (fopAcM_GetParam(ib) >> 0x10) & 0xFF; } + inline u16 getAdId(daIball_c* ib) { return fopAcM_GetParam(ib) & 0xFFFF; } +}; + +#endif /* D_A_IB_H */ diff --git a/include/d/actor/d_a_item.h b/include/d/actor/d_a_item.h index 8e2c5bf2c..b9f6ac7a2 100644 --- a/include/d/actor/d_a_item.h +++ b/include/d/actor/d_a_item.h @@ -71,6 +71,10 @@ public: BOOL checkActionNow(); u32 getItemNo() { return m_itemNo; } + void setItemTimerForIball(short param_1, short param_2) { + mDisappearTimer = param_1; + field_0x65a = param_2; + } static dCcD_SrcCyl m_cyl_src; static s32 m_timer_max; diff --git a/include/d/d_com_inf_game.h b/include/d/d_com_inf_game.h index 67af9b24f..6de237e2e 100644 --- a/include/d/d_com_inf_game.h +++ b/include/d/d_com_inf_game.h @@ -993,6 +993,14 @@ inline void dComIfGs_onSaveTbox(int i_stageNo, int i_no) { void dComIfGs_onStageTbox(int i_stageNo, int i_no); BOOL dComIfGs_isStageTbox(int i_stageNo, int i_no); +/** + * This does not appear in the demo debug maps, but it likely existed and was simply unused until the + * final release based on the fact that dComIfGs_onSaveSwitch does appear in the maps. + */ +inline BOOL dComIfGs_isSaveSwitch(int i_stageNo, int i_no) { + return g_dComIfG_gameInfo.save.getSavedata().getSave(i_stageNo).getBit().isSwitch(i_no); +} + inline void dComIfGs_onSaveSwitch(int i_stageNo, int i_no) { g_dComIfG_gameInfo.save.getSavedata().getSave(i_stageNo).getBit().onSwitch(i_no); } @@ -1089,7 +1097,7 @@ inline void dComIfGs_onItem(int bitNo, int roomNo) { g_dComIfG_gameInfo.save.onItem(bitNo, roomNo); } -inline bool dComIfGs_isItem(int bitNo, int roomNo) { +inline BOOL dComIfGs_isItem(int bitNo, int roomNo) { return g_dComIfG_gameInfo.save.isItem(bitNo, roomNo); } diff --git a/include/d/d_particle.h b/include/d/d_particle.h index 42e3b25b0..9d2624bf7 100644 --- a/include/d/d_particle.h +++ b/include/d/d_particle.h @@ -300,7 +300,10 @@ public: virtual void draw(JPABaseEmitter*); virtual void setup(JPABaseEmitter*, const cXyz*, const csXyz*, s8); -}; + +public: + /* 0x04 */ GXColor mColor; +}; // Size: 0x08 class dPa_modelControl_c { public: @@ -435,7 +438,10 @@ public: void drawModelParticle() { mModelCtrl->draw(); } JKRHeap * getHeap() { return mpHeap; } + static dPa_setColorEcallBack* getLifeBallSetColorEcallBack(int idx) { return &mLifeBall[idx]; } + static dPa_rippleEcallBack mSingleRippleEcallBack; + static dPa_setColorEcallBack mLifeBall[3]; /* 0x0000 */ JKRHeap* mpHeap; /* 0x0004 */ JPAResourceManager* mpCommonResMgr; diff --git a/include/f_op/f_op_actor_mng.h b/include/f_op/f_op_actor_mng.h index 321e98600..07f2c8755 100644 --- a/include/f_op/f_op_actor_mng.h +++ b/include/f_op/f_op_actor_mng.h @@ -309,8 +309,8 @@ inline void fopAcM_onItem(fopAc_ac_c* item, int bitNo) { dComIfGs_onItem(bitNo, fopAcM_GetHomeRoomNo(item)); } -inline bool dComIfGs_isItem(int bitNo, int roomNo); -inline bool fopAcM_isItem(fopAc_ac_c* item, int bitNo) { +inline BOOL dComIfGs_isItem(int bitNo, int roomNo); +inline BOOL fopAcM_isItem(fopAc_ac_c* item, int bitNo) { return dComIfGs_isItem(bitNo, fopAcM_GetHomeRoomNo(item)); } diff --git a/include/m_Do/m_Do_ext.h b/include/m_Do/m_Do_ext.h index 632a141be..d6c6525e3 100644 --- a/include/m_Do/m_Do_ext.h +++ b/include/m_Do/m_Do_ext.h @@ -35,11 +35,12 @@ public: void setLoopFrame(f32 i_frame) { mFrameCtrl->setLoop(i_frame); } BOOL isStop() { bool stopped = true; - if (!mFrameCtrl->checkState(1) && mFrameCtrl->getRate() != 0.0f) { + if (!mFrameCtrl->checkState(J3DFrameCtrl::STATE_STOP_E) && mFrameCtrl->getRate() != 0.0f) { stopped = false; } return stopped; } + BOOL isLoop() { return mFrameCtrl->checkState(J3DFrameCtrl::STATE_LOOP_E); } private: /* 0x4 */ J3DFrameCtrl* mFrameCtrl; @@ -365,7 +366,7 @@ public: void setFrame(f32 frame) { mFrameCtrl.setFrame((s16)frame); } BOOL isStop() { //regswap somewhere here bool stopped = true; - if (!mFrameCtrl.checkState(1) && mFrameCtrl.getRate() != 0.0f) { + if (!mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && mFrameCtrl.getRate() != 0.0f) { stopped = false; } return stopped; diff --git a/include/m_Do/m_Do_mtx.h b/include/m_Do/m_Do_mtx.h index cb9ca2672..ee65636b6 100644 --- a/include/m_Do/m_Do_mtx.h +++ b/include/m_Do/m_Do_mtx.h @@ -195,7 +195,7 @@ public: * Rotates the `now` matrix by the given csXyz in the order X, Y, Z * @param xyz The xyz rotation vector */ - static void XYZrotM(csXyz const& xyz); + static void XYZrotM(csXyz const& xyz) { XYZrotM(xyz.x, xyz.y, xyz.z); } static void ZXYrotS(csXyz const& xyz) { ZXYrotS(xyz.x, xyz.y, xyz.z); } diff --git a/src/d/actor/d_a_am.cpp b/src/d/actor/d_a_am.cpp index 1fa137702..3b70f4339 100644 --- a/src/d/actor/d_a_am.cpp +++ b/src/d/actor/d_a_am.cpp @@ -587,7 +587,7 @@ static void action_dousa(am_class* i_this) { // if (!i_this->mpMorf->isStop()) { mDoExt_McaMorf* morf = i_this->mpMorf; bool stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (!stopped) { break; } @@ -658,7 +658,7 @@ static void action_dousa(am_class* i_this) { // if (i_this->mpMorf->isStop()) { mDoExt_McaMorf* morf = i_this->mpMorf; bool stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (stopped) { anm_init(i_this, AM_BCK_CLOSE_LOOP, 1.0f, J3DFrameCtrl::LOOP_REPEAT_e, 1.0f, -1); } @@ -733,7 +733,7 @@ static void action_dousa(am_class* i_this) { // if (i_this->mpMorf->isStop()) { morf = i_this->mpMorf; stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (stopped) { i_this->mState = 0; } @@ -862,7 +862,7 @@ static void action_itai_move(am_class* i_this) { // if (!i_this->mpMorf->isStop()) { mDoExt_McaMorf* morf = i_this->mpMorf; bool stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (!stopped) { break; } @@ -888,7 +888,7 @@ static void action_itai_move(am_class* i_this) { // if (!i_this->mpMorf->isStop()) { morf = i_this->mpMorf; stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (!stopped) { break; } @@ -938,7 +938,7 @@ static void action_itai_move(am_class* i_this) { // if (!i_this->mpMorf->isStop()) { morf = i_this->mpMorf; stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (!stopped) { break; } @@ -997,7 +997,7 @@ static void action_itai_move(am_class* i_this) { // if (!i_this->mpMorf->isStop()) { morf = i_this->mpMorf; stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (!stopped) { break; } diff --git a/src/d/actor/d_a_am2.cpp b/src/d/actor/d_a_am2.cpp index 7809f7c25..800cc27d1 100644 --- a/src/d/actor/d_a_am2.cpp +++ b/src/d/actor/d_a_am2.cpp @@ -567,7 +567,7 @@ static void action_dousa(am2_class* i_this) { // if (!i_this->mpMorf->isStop()) { mDoExt_McaMorf* morf = i_this->mpMorf; bool stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (!stopped) { break; } @@ -656,7 +656,7 @@ static void action_dousa(am2_class* i_this) { // if (!i_this->mpMorf->isStop()) { morf = i_this->mpMorf; stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (stopped) { for (int i = 0; i < ARRAY_SIZE(i_this->mCountUpTimers); i++) { i_this->mCountUpTimers[i] = 0; @@ -724,7 +724,7 @@ static void action_mahi(am2_class* i_this) { // if (!i_this->mpMorf->isStop()) { mDoExt_McaMorf* morf = i_this->mpMorf; bool stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (stopped) { actor->speedF = 0.0f; i_this->mCountDownTimers[2] = 20*30; @@ -969,7 +969,7 @@ static void action_itai(am2_class* i_this) { // if (!i_this->mpMorf->isStop()) { mDoExt_McaMorf* morf = i_this->mpMorf; bool stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (!stopped) { break; } @@ -1025,7 +1025,7 @@ static void action_itai(am2_class* i_this) { // if (!i_this->mpMorf->isStop()) { morf = i_this->mpMorf; stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (!stopped) { break; } diff --git a/src/d/actor/d_a_dr.cpp b/src/d/actor/d_a_dr.cpp index ffd77f47b..a813c2b06 100644 --- a/src/d/actor/d_a_dr.cpp +++ b/src/d/actor/d_a_dr.cpp @@ -132,7 +132,7 @@ static void move(dr_class* i_this) { // if (i_this->mpMorf->isStop()) { mDoExt_McaMorf* morf = i_this->mpMorf; bool stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (stopped) { i_this->mState = 0; } @@ -153,7 +153,7 @@ static void move(dr_class* i_this) { // if (i_this->mpMorf->isStop()) { morf = i_this->mpMorf; stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (stopped) { i_this->m2C9 = 1; if (i_this->mpBreathEmitter) { @@ -205,7 +205,7 @@ static void move(dr_class* i_this) { // if (i_this->mpMorf->isStop()) { morf = i_this->mpMorf; stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (stopped) { i_this->mState = 0; if (i_this->mpBreathEmitter) { diff --git a/src/d/actor/d_a_ib.cpp b/src/d/actor/d_a_ib.cpp index a45a3d5bb..9abbd2434 100644 --- a/src/d/actor/d_a_ib.cpp +++ b/src/d/actor/d_a_ib.cpp @@ -3,136 +3,551 @@ // Translation Unit: d_a_ib.cpp // -#include "d_a_ib.h" -#include "dolphin/types.h" +#include "d/actor/d_a_ib.h" +#include "d/d_procname.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "d/d_com_inf_game.h" +#include "d/d_s_play.h" +#include "d/actor/d_a_item.h" +#include "d/d_item.h" +#include "d/d_item_data.h" +#include "m_Do/m_Do_mtx.h" + +// Needed for the .data section to match. +static f32 dummy1[3] = {1.0f, 1.0f, 1.0f}; +static f32 dummy2[3] = {1.0f, 1.0f, 1.0f}; + +struct daIball_c__data { + /* 0x00 */ u8 m00; + /* 0x01 */ u8 m01; + /* 0x02 */ u8 m02; + /* 0x03 */ u8 m03; + /* 0x04 */ f32 mPlaySpeeds[4]; + /* 0x14 */ f32 mBounceSpeedMult; + /* 0x18 */ f32 mGravity; + /* 0x1C */ f32 mYOffset; + /* 0x20 */ f32 m20; + /* 0x24 */ f32 m24; + /* 0x28 */ s16 mMoveDelay; + /* 0x2C */ f32 mSpeedF; + /* 0x30 */ f32 mSpeedY; + /* 0x34 */ f32 mRandSpeedF; + /* 0x38 */ s16 m38; + /* 0x3A */ s16 m3A; +}; + +const daIball_c__data m_data = { + /* m00 */ 1, + /* m01 */ 2, + /* m02 */ 4, + /* m03 */ 5, + /* mPlaySpeeds */ {1.0f, 2.0f, 4.0f, 8.0f}, + /* mBounceSpeedMult */ 0.5f, + /* mGravity */ -7.0f, + /* mYOffset */ 40.0f, + /* m20 */ 0.5f, + /* m24 */ 0.75f, + /* mMoveDelay */ 32, + /* mSpeedF */ 10.0f, + /* mSpeedY */ 53.0f, + /* mRandSpeedF */ 4.0f, + /* m38 */ 80, + /* m3A */ 60, +}; /* 800F3228-800F3380 .text setPointLight__9daIball_cFv */ void daIball_c::setPointLight() { - /* Nonmatching */ + static const s16 light_color[3][3] = { + {800, 120, 400}, + {120, 400, 600}, + {600, 600, 200}, + }; + int color_idx; + f32 frame = mBrkAnm[0].getFrame(); + if (frame >= 0.0f && frame < 45.0f) { + color_idx = 0; + } else if (frame >= 45.0f && frame < 90.0f) { + color_idx = 1; + } else if (frame >= 90.0f && frame <= 135.0f) { + color_idx = 2; + } + cLib_addCalc2(&mLightFlickerMult, 1.0f + cM_rndF(0.2f), 0.5f, 0.02f); + mLight.mPos = current.pos; + mLight.mColor.r = light_color[color_idx][0]; + mLight.mColor.g = light_color[color_idx][1]; + mLight.mColor.b = light_color[color_idx][2]; + s16 power = (80.0f + g_regHIO.mChild[12].mFloatRegs[0]) * mLightFlickerMult; + mLight.mPower = power; + mLight.mFluctuation = 250.0f; } /* 800F3380-800F3608 .text createDisappearEffect__9daIball_cFii */ -void daIball_c::createDisappearEffect(int, int) { - /* Nonmatching */ +void daIball_c::createDisappearEffect(int param_1, int color_idx) { + cXyz scale; + scale.setall(1.0f); + cXyz pos(current.pos); + pos.y += m_data.mYOffset; + switch (param_1) { + case 0: + dComIfGp_particle_set(0x1C, &pos, NULL, &scale, 0xFF, dPa_control_c::getLifeBallSetColorEcallBack(color_idx)); + dComIfGp_particle_set(0x1D, &pos, NULL, &scale); + if (color_idx == 2) { + dComIfGp_particle_set(0x47, &pos); + } + fopAcM_seStartCurrent(this, JA_SE_OBJ_CUT_INOCHIDAMA, 0); + break; + case 1: + dComIfGp_particle_set(0x19, &pos, NULL, &scale); + dComIfGp_particle_set(0x1A, &pos, NULL, &scale); + dComIfGp_particle_set(0x1B, &pos, NULL, &scale); + fopAcM_seStartCurrent(this, JA_SE_CM_INOCHIDAMA_BREAK, 0); + break; + } } /* 800F3608-800F3658 .text itemParamSet_CB__FPv */ -void itemParamSet_CB(void*) { - /* Nonmatching */ +static BOOL itemParamSet_CB(void* i_actor) { + daItem_c* item = static_cast(i_actor); + if (item && !isEmono(item->getItemNo())) { + item->setItemTimerForIball(3*30, 2*30); + } + return TRUE; +} + +// This is a fake inline, not present in the demo debug map. +// However, it's possible an inline similar to this was added to the final release. +// The kiosk demo calls dSv_memBit_c::isVisitedRoom(int) instead of dSv_memBit_c::isSwitch(int) here, +// so it's plausible they also added this inline while they were modifying that code. +inline BOOL isItemBit(u8 itemNo, s8 itemBitNo, s8 roomNo) { + if (itemNo == BLUE_JELLY) { // Blue Chu Jelly uses itemBitNo as if it was a switch. + return dComIfGs_isSaveSwitch(0xE, itemBitNo); + } else { + return dComIfGs_isItem(itemBitNo, roomNo); + } } /* 800F3658-800F3994 .text createItem__9daIball_cFv */ -void daIball_c::createItem() { - /* Nonmatching */ +BOOL daIball_c::createItem() { + // Fakematch: itemBitNo and itemTableIdx should really be separate variables as they aren't + // related, but we need r27 to be used for both of them in order for the regalloc to match. + int itemBitNo = daIball_prm::getAdId(this); + int itemTableIdx = itemBitNo; + u32 items[8]; + + items[0] = dComIfGp_CharTbl()->GetInf(dComIfGp_CharTbl()->mIndex_ITEM0, itemTableIdx); + items[1] = dComIfGp_CharTbl()->GetInf(dComIfGp_CharTbl()->mIndex_ITEM1, itemTableIdx); + items[2] = dComIfGp_CharTbl()->GetInf(dComIfGp_CharTbl()->mIndex_ITEM2, itemTableIdx); + items[3] = dComIfGp_CharTbl()->GetInf(dComIfGp_CharTbl()->mIndex_ITEM3, itemTableIdx); + items[4] = dComIfGp_CharTbl()->GetInf(dComIfGp_CharTbl()->mIndex_ITEM4, itemTableIdx); + items[5] = dComIfGp_CharTbl()->GetInf(dComIfGp_CharTbl()->mIndex_ITEM5, itemTableIdx); + items[6] = dComIfGp_CharTbl()->GetInf(dComIfGp_CharTbl()->mIndex_ITEM6, itemTableIdx); + items[7] = dComIfGp_CharTbl()->GetInf(dComIfGp_CharTbl()->mIndex_ITEM7, itemTableIdx); + + for (int i = 0; i < 8; i++) { + itemBitNo = -1; + if (isLimitedItem(items[i])) { + itemBitNo = daIball_prm::getItemBitNo(this); + if (itemBitNo == 0x1F || itemBitNo == 0xFF || itemBitNo == -1 || isItemBit(items[i], itemBitNo, current.roomNo)) { + itemBitNo = -1; + items[i] = YELLOW_RUPEE; + } + } else if (isNonSavedEmono(items[i])) { + if (daIball_prm::getItemBitNo(this) != 0) { + items[i] = YELLOW_RUPEE; + } + itemBitNo = -1; + } + + cXyz scale = cXyz::Zero; + csXyz angle = csXyz::Zero; + + f32 speed_f = 1.0f; + if (cM_rndFX(1.0f) < 0.0f) { + speed_f = -1.0f; + } + speed_f = speed_f*m_data.mSpeedF + cM_rndFX(m_data.mRandSpeedF); + + angle.y = (s16)cM_rndF((f32)0x7FFF); + + items[i] = getItemNoByLife(items[i]); + + s8 roomNo = current.roomNo; + fopAcM_fastCreateItem( + ¤t.pos, items[i], roomNo, &angle, &scale, + speed_f, m_data.mSpeedY + cM_rndF(10.0f), -6.0f, itemBitNo, itemParamSet_CB + ); + } + + dead(); + + return TRUE; } /* 800F3994-800F3A48 .text dead__9daIball_cFv */ -void daIball_c::dead() { - /* Nonmatching */ +BOOL daIball_c::dead() { + int color_idx; + f32 frame = mBrkAnm[0].getFrame(); + if (frame >= 0.0f && frame < 45.0f) { + color_idx = 0; + } else if (frame >= 45.0f && frame < 90.0f) { + color_idx = 1; + } else if (frame >= 90.0f && frame <= 135.0f) { + color_idx = 2; + } + createDisappearEffect(0, color_idx); + fopAcM_delete(this); + return TRUE; } /* 800F3A48-800F3E78 .text checkGeo__9daIball_cFv */ void daIball_c::checkGeo() { - /* Nonmatching */ + static ModeFunc mode_proc[] = { + &mode_wait, + &mode_water, + }; + + mPrevSpeedY = speed.y; + if (mTimer > m_data.mMoveDelay) { + fopAcM_posMoveF(this, mStts.GetCCMoveP()); + } + mAcch.CrrPos(*dComIfG_Bgsp()); + + (this->*mode_proc[mMode])(); + + dBgS_ObjGndChk_Yogan gnd_chk; + cXyz pos(current.pos.x, next.pos.y + 30.0f + m_data.mYOffset, current.pos.z); + gnd_chk.SetPos(&pos); + f32 groundY = dComIfG_Bgsp()->GroundCross(&gnd_chk); + f32 groundH = mAcch.GetGroundH(); + if (groundY != -1000000000.0f) { + f32 dist_off_gnd = groundY - groundH; + if ((dist_off_gnd < 20.0f && groundY > current.pos.y) || (dist_off_gnd >= 20.0f && groundY > current.pos.y + 20.0f)) { + fopAcM_seStartCurrent(this, JA_SE_OBJ_FALL_MAGMA_S, 0); + cXyz particle_scale; + particle_scale.setall(0.25f); + cXyz particle_pos(current.pos); + particle_pos.y = groundY; + dComIfGp_particle_set(0x80D5, &particle_pos, NULL, &particle_scale); + fopAcM_delete(this); + } + } } /* 800F3E78-800F3EB0 .text mode_wait_init__9daIball_cFv */ void daIball_c::mode_wait_init() { - /* Nonmatching */ + mRippleCb.end(); + mMode = MODE_WAIT; } /* 800F3EB0-800F3F6C .text mode_wait__9daIball_cFv */ void daIball_c::mode_wait() { - /* Nonmatching */ + if (mAcch.ChkGroundLanding()) { + mPrevSpeedY *= m_data.mBounceSpeedMult; + if (mPrevSpeedY > mGravity - 0.5f) { + speedF = 0.0f; + } else { + speed.set(0.0f, -mPrevSpeedY, 0.0f); + } + } + + f32 seaHeight = mAcch.GetSeaHeight(); + if (seaHeight > current.pos.y && seaHeight != -1000000000.0f) { + mode_water_init(); + current.pos.y = seaHeight; + } } /* 800F3F6C-800F3FE8 .text mode_water_init__9daIball_cFv */ void daIball_c::mode_water_init() { - /* Nonmatching */ + dComIfGp_particle_setShipTail(0x33, ¤t.pos, NULL, &mScale, 0xFF, &mRippleCb); + mRippleCb.setRate(0.0f); + mMode = MODE_WATER; } /* 800F3FE8-800F4054 .text mode_water__9daIball_cFv */ void daIball_c::mode_water() { - /* Nonmatching */ + f32 seaHeight = mAcch.GetSeaHeight(); + if (seaHeight == -1000000000.0f || seaHeight < current.pos.y) { + mode_wait_init(); + } + if (seaHeight != -1000000000.0f) { + current.pos.y = seaHeight; + } } /* 800F4054-800F418C .text animControl__9daIball_cFv */ void daIball_c::animControl() { - /* Nonmatching */ + BOOL isEventRun = FALSE; + if (dComIfGp_event_runCheck()) { + isEventRun = TRUE; + } + + mBrkAnm[0].setPlaySpeed(m_data.mPlaySpeeds[mPlaySpeedIdx]); + mBrkAnm[0].play(); + BOOL isLoop = mBrkAnm[0].isLoop(); + mBrkAnm[1].setPlaySpeed(1.0f); + mBrkAnm[1].play(); + mBtkAnm.setPlaySpeed(1.0f); + mBtkAnm.play(); + mBckAnm.play(); + + if (!isEventRun) { + f32 frame = mBrkAnm[0].getFrame(); + f32 prevFrame = frame - mBrkAnm[0].getPlaySpeed(); + if (isLoop || + (frame >= 45.0f && prevFrame < 45.0f) || + (frame >= 90.0f && prevFrame < 90.0f)) + { + fopAcM_seStartCurrent(this, JA_SE_CM_INOCHIDAMA_BLINK, 0); + } + } } /* 800F418C-800F4250 .text damage__9daIball_cFv */ void daIball_c::damage() { - /* Nonmatching */ + if (mCyl.ChkTgHit()) { + cCcD_Obj* hitObj = mCyl.GetTgHitObj(); + if (hitObj) { + u32 atType = hitObj->GetAtType(); + if (atType & AT_TYPE_SWORD || atType & AT_TYPE_BOKO_STICK || + atType & AT_TYPE_MACHETE || atType & AT_TYPE_SKULL_HAMMER || + atType & AT_TYPE_UNK2000000 || atType & AT_TYPE_STALFOS_MACE || + atType & AT_TYPE_DARKNUT_SWORD || atType & AT_TYPE_UNK8000 || + atType & AT_TYPE_BOOMERANG || atType & AT_TYPE_NORMAL_ARROW || + atType & AT_TYPE_FIRE_ARROW || atType & AT_TYPE_ICE_ARROW || + atType & AT_TYPE_LIGHT_ARROW || atType & AT_TYPE_MOBLIN_SPEAR) + { + createItem(); + } + } + } } /* 800F4250-800F42E8 .text set_mtx__9daIball_cFv */ void daIball_c::set_mtx() { - /* Nonmatching */ + mpModel->setBaseScale(mScale); + mDoMtx_stack_c::transS(current.pos.x, current.pos.y + m_data.mYOffset, current.pos.z); + mDoMtx_stack_c::XYZrotM(current.angle); + mpModel->setBaseTRMtx(mDoMtx_stack_c::get()); } +// TODO: This is a hack. I have no idea why this one variable needs to go in .data instead of .sdata. +#ifndef __INTELLISENSE__ +__declspec(section ".data") +#endif +char daIball_c::m_arcname[] = "Always"; + +dCcD_SrcCyl daIball_c::m_cyl_src = { + // dCcD_SrcGObjInf + { + /* Flags */ 0, + /* SrcObjAt Type */ 0, + /* SrcObjAt Atp */ 0, + /* SrcObjAt SPrm */ 0, + /* SrcObjTg Type */ ~(AT_TYPE_LIGHT), + /* SrcObjTg SPrm */ 0x09, + /* SrcObjCo SPrm */ 0x79, + /* SrcGObjAt Se */ 0, + /* SrcGObjAt HitMark */ 0, + /* SrcGObjAt Spl */ 0, + /* SrcGObjAt Mtrl */ 0, + /* SrcGObjAt GFlag */ 0x04, + /* SrcGObjTg Se */ 0, + /* SrcGObjTg HitMark */ 0, + /* SrcGObjTg Spl */ 0, + /* SrcGObjTg Mtrl */ 0, + /* SrcGObjTg GFlag */ 0x04, + /* SrcGObjCo GFlag */ 0, + }, + // cM3dGCylS + { + /* Center */ 0.0f, 0.0f, 0.0f, + /* Radius */ 30.0f, + /* Height */ 80.0f, + }, +}; + /* 800F42E8-800F441C .text CreateInit__9daIball_cFv */ void daIball_c::CreateInit() { - /* Nonmatching */ + fopAcM_SetMtx(this, mpModel->getBaseTRMtx()); + mStts.Init(0xFF, 0xFF, this); + mCyl.Set(m_cyl_src); + mCyl.SetStts(&mStts); + mAcchCir.SetWall(30.0f, 30.0f); + mAcch.Set(¤t.pos, &next.pos, this, 1, &mAcchCir, &speed, NULL, NULL); + mAcch.OnSeaCheckOn(); + mAcch.OnSeaWaterHeight(); + + mbPlayedSe = false; + mGravity = m_data.mGravity; + mMode = MODE_WAIT; + current.pos.y -= m_data.mYOffset; + + mBckAnm.entry(mpModel->getModelData()); + + set_mtx(); + + mpModel->calc(); + dKy_plight_set(&mLight); + setPointLight(); + + mLightFlickerMult = 1.0f; + regist(this); } /* 800F441C-800F4544 .text _daIball_draw__9daIball_cFv */ -void daIball_c::_daIball_draw() { - /* Nonmatching */ +BOOL daIball_c::_daIball_draw() { + g_env_light.settingTevStruct(TEV_TYPE_ACTOR, ¤t.pos, &mTevStr); + g_env_light.setLightTevColorType(mpModel, &mTevStr); + + for (int i = 0; i < (int)ARRAY_SIZE(mBrkAnm); i++) { + mBrkAnm[i].entry(mpModel->getModelData()); + } + mBtkAnm.entry(mpModel->getModelData()); + mBckAnm.entry(mpModel->getModelData()); + + dComIfGd_setListMaskOff(); + mDoExt_modelUpdateDL(mpModel); + dComIfGd_setList(); + + dComIfGd_setSimpleShadow2( + ¤t.pos, mAcch.GetGroundH(), 30.0f, mAcch.m_gnd, + 0, 1.0f, dDlst_shadowControl_c::getSimpleTex() + ); + + return TRUE; } /* 800F4544-800F4634 .text _daIball_execute__9daIball_cFv */ -void daIball_c::_daIball_execute() { - /* Nonmatching */ +BOOL daIball_c::_daIball_execute() { + mEyePos = current.pos; + mEyePos.y = current.pos.y + 45.0f; + + mTimer++; + + setPointLight(); + + if (!mbPlayedSe) { + fopAcM_seStartCurrent(this, JA_SE_CM_INOCHIDAMA, 0); + mbPlayedSe = true; + } + + checkGeo(); + animControl(); + damage(); + set_mtx(); + + mCyl.SetC(current.pos); + dComIfG_Ccsp()->Set(&mCyl); + + return TRUE; } /* 800F4634-800F4678 .text _daIball_delete__9daIball_cFv */ -void daIball_c::_daIball_delete() { - /* Nonmatching */ +BOOL daIball_c::_daIball_delete() { + mRippleCb.end(); + dKy_plight_cut(&mLight); + remove(this); + return TRUE; } /* 800F4678-800F4698 .text CheckCreateHeap__FP10fopAc_ac_c */ -void CheckCreateHeap(fopAc_ac_c*) { - /* Nonmatching */ +static void CheckCreateHeap(fopAc_ac_c* i_this) { + static_cast(i_this)->CreateHeap(); } /* 800F4698-800F4870 .text _daIball_create__9daIball_cFv */ -void daIball_c::_daIball_create() { - /* Nonmatching */ -} - -/* 800F4870-800F489C .text __ct__13mDoExt_brkAnmFv */ -mDoExt_brkAnm::mDoExt_brkAnm() { - /* Nonmatching */ +s32 daIball_c::_daIball_create() { + fopAcM_SetupActor(this, daIball_c); + + if (!fopAcM_entrySolidHeap(this, (heapCallbackFunc)CheckCreateHeap, 0x3500)) { + return cPhs_ERROR_e; + } + + CreateInit(); + + return cPhs_COMPLEATE_e; } /* 800F489C-800F4B40 .text CreateHeap__9daIball_cFv */ -void daIball_c::CreateHeap() { - /* Nonmatching */ +BOOL daIball_c::CreateHeap() { + J3DModelData* modelData = (J3DModelData*)dComIfG_getObjectRes(m_arcname, ALWAYS_BDL_IB); + JUT_ASSERT(1135, modelData != 0); + mpModel = mDoExt_J3DModel__create(modelData, 0x80000, 0x11000222); + if (!mpModel) { return FALSE; } + + J3DAnmTransform* pbck = (J3DAnmTransform*)dComIfG_getObjectRes(m_arcname, ALWAYS_BCK_START); + JUT_ASSERT(1152, pbck != 0); + int ret = mBckAnm.init(modelData, pbck, 1, J3DFrameCtrl::LOOP_ONCE_e, 1.0f, 0, -1, false); + if (!ret) { return FALSE; } + + J3DAnmTextureSRTKey* pbtk = (J3DAnmTextureSRTKey*)dComIfG_getObjectRes(m_arcname, ALWAYS_BTK_IB); + JUT_ASSERT(1164, pbtk != 0); + ret = mBtkAnm.init(modelData, pbtk, 1, J3DFrameCtrl::LOOP_REPEAT_e, 1.0f, 0, -1, false, 0); + if (!ret) { return FALSE; } + + int brkIds[ARRAY_SIZE(mBrkAnm)] = { + ALWAYS_BRK_IB_01, + ALWAYS_BRK_IB_02, + }; + J3DAnmTevRegKey* pbrk; + for (int i = 0; i < (int)ARRAY_SIZE(mBrkAnm); i++) { + pbrk = (J3DAnmTevRegKey*)dComIfG_getObjectRes(m_arcname, brkIds[i]); + JUT_ASSERT(1182, pbrk != 0); + ret = mBrkAnm[i].init(modelData, pbrk, 1, J3DFrameCtrl::LOOP_REPEAT_e, 1.0f, 0, -1, false, 0); + if (!ret) { return FALSE; } + } + + return TRUE; } /* 800F4B40-800F4B60 .text daIball_Create__FP10fopAc_ac_c */ -void daIball_Create(fopAc_ac_c*) { - /* Nonmatching */ +static s32 daIball_Create(fopAc_ac_c* i_this) { + return static_cast(i_this)->_daIball_create(); } /* 800F4B60-800F4B80 .text daIball_Draw__FP9daIball_c */ -void daIball_Draw(daIball_c*) { - /* Nonmatching */ +static BOOL daIball_Draw(daIball_c* i_this) { + return i_this->_daIball_draw(); } /* 800F4B80-800F4BA0 .text daIball_Delete__FP9daIball_c */ -void daIball_Delete(daIball_c*) { - /* Nonmatching */ +static BOOL daIball_Delete(daIball_c* i_this) { + return i_this->_daIball_delete(); } /* 800F4BA0-800F4BA8 .text daIball_IsDelete__FP9daIball_c */ -void daIball_IsDelete(daIball_c*) { - /* Nonmatching */ +static BOOL daIball_IsDelete(daIball_c* i_this) { + return TRUE; } /* 800F4BA8-800F4BC8 .text daIball_Execute__FP9daIball_c */ -void daIball_Execute(daIball_c*) { - /* Nonmatching */ +static BOOL daIball_Execute(daIball_c* i_this) { + return i_this->_daIball_execute(); } +actor_method_class l_daIball_Method = { + (process_method_func)daIball_Create, + (process_method_func)daIball_Delete, + (process_method_func)daIball_Execute, + (process_method_func)daIball_IsDelete, + (process_method_func)daIball_Draw, +}; + +actor_process_profile_definition g_profile_Iball = { + /* LayerID */ fpcLy_CURRENT_e, + /* ListID */ 7, + /* ListPrio */ fpcLy_CURRENT_e, + /* ProcName */ PROC_Iball, + /* Proc SubMtd */ &g_fpcLf_Method.mBase, + /* Size */ sizeof(daIball_c), + /* SizeOther */ 0, + /* Parameters */ 0, + /* Leaf SubMtd */ &g_fopAc_Method.base, + /* Priority */ 0x0187, + /* Actor SubMtd */ &l_daIball_Method, + /* Status */ fopAcStts_CULL_e | fopAcStts_UNK4000_e | fopAcStts_UNK40000_e, + /* Group */ fopAc_ACTOR_e, + /* CullType */ fopAc_CULLBOX_0_e, +}; diff --git a/src/d/actor/d_a_obj_toripost.cpp b/src/d/actor/d_a_obj_toripost.cpp index 15f670ea0..ab0c65af0 100644 --- a/src/d/actor/d_a_obj_toripost.cpp +++ b/src/d/actor/d_a_obj_toripost.cpp @@ -307,10 +307,10 @@ void daObjTpost_c::cutSetAnmStart(int staffIdx) { void daObjTpost_c::cutSetAnmProc(int staffIdx) { // Using the mDoExt_McaMorf::isStop inline causes regswap. - // if(mMorf->isStop()) { // + // if(mMorf->isStop()) { mDoExt_McaMorf* morf = mMorf; bool stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (stopped) { dComIfGp_evmng_cutEnd(staffIdx); } @@ -845,7 +845,7 @@ void daObjTpost_c::modeTalkXY() { // if(mMorf->isStop()) { mDoExt_McaMorf* morf = mMorf; bool stopped = true; - if (!morf->mFrameCtrl.checkState(1) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } + if (!morf->mFrameCtrl.checkState(J3DFrameCtrl::STATE_STOP_E) && morf->mFrameCtrl.getRate() != 0.0f) { stopped = false; } if (stopped) { if(cLib_calcTimer(&field_0x8DC) == 0 && talk(1) == dNpcMsgStts_BOX_CLOSED_e) { modeProc(PROC_INIT, 0); diff --git a/src/d/d_com_static.cpp b/src/d/d_com_static.cpp index 4226a222e..e3aac8555 100644 --- a/src/d/d_com_static.cpp +++ b/src/d/d_com_static.cpp @@ -9,6 +9,7 @@ #include "d/actor/d_a_agbsw0.h" #include "d/actor/d_a_npc_md.h" #include "d/actor/d_a_arrow.h" +#include "d/actor/d_a_ib.h" #include "d/actor/d_a_obj_movebox.h" #include "d/actor/d_a_tag_kb_item.h" #include "d/actor/d_a_item.h" @@ -128,25 +129,52 @@ void daArrow_c::setKeepType(u8 type) { m_keep_type = type; } -// /* 800568D0-800568F8 .text init__9daIball_cFv */ -// void daIball_c::init() { -// /* Nonmatching */ -// } +u32 daIball_c::m_ib_actor[5]; -// /* 800568F8-80056944 .text regist__9daIball_cFP10fopAc_ac_c */ -// void daIball_c::regist(fopAc_ac_c*) { -// /* Nonmatching */ -// } +/* 800568D0-800568F8 .text init__9daIball_cFv */ +void daIball_c::init() { + for (int i = 0; i < ARRAY_SIZE(m_ib_actor); i++) { + m_ib_actor[i] = -1; + } +} -// /* 80056944-80056990 .text remove__9daIball_cFP10fopAc_ac_c */ -// void daIball_c::remove(fopAc_ac_c*) { -// /* Nonmatching */ -// } +/* 800568F8-80056944 .text regist__9daIball_cFP10fopAc_ac_c */ +void daIball_c::regist(fopAc_ac_c* i_actor) { + for (int i = 0; i < ARRAY_SIZE(m_ib_actor); i++) { + if (m_ib_actor[i] == -1) { + m_ib_actor[i] = fopAcM_GetID(i_actor); + break; + } + } +} -// /* 80056990-80056A18 .text remove_old__9daIball_cFv */ -// void daIball_c::remove_old() { -// /* Nonmatching */ -// } +/* 80056944-80056990 .text remove__9daIball_cFP10fopAc_ac_c */ +void daIball_c::remove(fopAc_ac_c* i_actor) { + for (int i = 0; i < ARRAY_SIZE(m_ib_actor); i++) { + if (m_ib_actor[i] == fopAcM_GetID(i_actor)) { + m_ib_actor[i] = -1; + break; + } + } +} + +/* 80056990-80056A18 .text remove_old__9daIball_cFv */ +void daIball_c::remove_old() { + u32 iball_id = -1; + for (int i = 0; i < ARRAY_SIZE(m_ib_actor); i++) { + if (m_ib_actor[i] == -1) { + return; + } + if (m_ib_actor[i] < iball_id) { + iball_id = m_ib_actor[i]; + } + } + fopAc_ac_c* iball = fopAcM_SearchByID(iball_id); + if (iball) { + static_cast(iball)->dead(); + remove(iball); + } +} // /* 80056A18-80056AD0 .text getCreateCount__13daObj_Roten_cFv */ // void daObj_Roten_c::getCreateCount() {