diff options
| author | elijah-thomas774 <elijahthomas774@gmail.com> | 2026-09-24 18:15:38 -0400 |
|---|---|---|
| committer | elijah-thomas774 <elijahthomas774@gmail.com> | 2026-09-24 18:15:38 -0400 |
| commit | e9199fba27c8f193dc0c7d36daf73006d8dc5e19 (patch) | |
| tree | 32bc11c6d45b2cc14b8a2139072f787b558d462e /src | |
| parent | fe566ba5dbc764a01774643f8a47b7ff5d53fd87 (diff) | |
| parent | df3d2023e89b5b89f2ecb9f53faa9b0e61e2c958 (diff) | |
Merge remote-tracking branch 'upstream/HEAD' into d_a_e_skytail
Diffstat (limited to 'src')
| -rw-r--r-- | src/REL/d/a/d_a_bombf.cpp | 38 | ||||
| -rw-r--r-- | src/REL/d/a/e/d_a_e_ks.cpp | 14 | ||||
| -rw-r--r-- | src/REL/d/a/e/d_a_e_remly.cpp | 4 | ||||
| -rw-r--r-- | src/REL/d/a/e/d_a_e_sm.cpp | 6 | ||||
| -rw-r--r-- | src/REL/d/a/obj/d_a_obj_barrel.cpp | 10 | ||||
| -rw-r--r-- | src/REL/d/a/obj/d_a_obj_tubo.cpp | 2 | ||||
| -rw-r--r-- | src/REL/d/t/d_t_action.cpp | 2 | ||||
| -rw-r--r-- | src/d/a/d_a_item.cpp | 2 | ||||
| -rw-r--r-- | src/d/a/d_a_player.cpp | 143 | ||||
| -rw-r--r-- | src/d/a/obj/d_a_obj_bomb.cpp | 1240 | ||||
| -rw-r--r-- | src/d/a/obj/d_a_obj_boomerang.cpp | 2 | ||||
| -rw-r--r-- | src/d/col/bg/d_bg_s_acch.cpp | 24 | ||||
| -rw-r--r-- | src/d/d_player_mdl.cpp | 5 | ||||
| -rw-r--r-- | src/d/lyt/d_lyt_do_button.cpp | 3 | ||||
| -rw-r--r-- | src/d/lyt/meter/d_lyt_meter_item_select.cpp | 15 | ||||
| -rw-r--r-- | src/d/tg/d_t_alldie.cpp | 112 | ||||
| -rw-r--r-- | src/d/tg/d_t_view_clip.cpp | 93 |
17 files changed, 1652 insertions, 63 deletions
diff --git a/src/REL/d/a/d_a_bombf.cpp b/src/REL/d/a/d_a_bombf.cpp index d94a76d0..d1cfd327 100644 --- a/src/REL/d/a/d_a_bombf.cpp +++ b/src/REL/d/a/d_a_bombf.cpp @@ -14,6 +14,13 @@ SPECIAL_ACTOR_PROFILE(BOMBF, dAcBombf_c, fProfile::BOMBF, 0x129, 0, 4099); STATE_DEFINE(dAcBombf_c, Wait); +class dAcBombf_HIO_c { +public: + inline static const char *getBombName() { + return "Bomb"; + } +}; + bool dAcBombf_c::createHeap() { nw4r::g3d::ResFile resFile(getOarcResFile("FlowerBomb")); nw4r::g3d::ResMdl resMdl = resFile.GetResMdl("LeafBomb"); @@ -30,8 +37,8 @@ int dAcBombf_c::actorCreate() { CREATE_ALLOCATOR(dAcBombf_c); field_0x3D2 = (mParams >> 4) & 0xF; - field_0x3D0 = field_0x3D2 == 1; - if (field_0x3D0) { + mIsUnderground = field_0x3D2 == 1; + if (mIsUnderground) { mModel.setPriorityDraw(0x82, 0x7F); } @@ -133,7 +140,7 @@ int dAcBombf_c::actorExecute() { } int dAcBombf_c::draw() { - if (field_0x3D0 != 0 && !dAcPy_c::LINK->checkActionFlagsCont(0x400000)) { + if (mIsUnderground != 0 && !dAcPy_c::LINK->checkActionFlagsCont(0x400000)) { return SUCCEEDED; } drawModelType1(&mModel); @@ -143,15 +150,12 @@ int dAcBombf_c::draw() { void dAcBombf_c::regrowBomb() { // These params are hell s8 viewclip_idx = checkActorProperty(dAcBase_c::AC_PROP_0x1) ? mViewClipIdx : -1; - u32 actorParams1; - actorParams1 = 1; - if (field_0x3D0) { - actorParams1 = 2; - } - dAcObjBase_c *ac = dAcObjBase_c::create( - "Bomb", mRoomID, actorParams1, &mPosition, nullptr, nullptr, 0xFFFFFFFF, 0xFFFF, viewclip_idx + u32 bombType = mIsUnderground ? dAcBomb_c::BOMBF_CRAWLSPACE : dAcBomb_c::BOMBF; + const char *name = dAcBombf_HIO_c::getBombName(); + dAcBomb_c *ac = static_cast<dAcBomb_c *>( + dAcObjBase_c::create(name, mRoomID, bombType, &mPosition, nullptr, nullptr, 0xFFFFFFFF, 0xFFFF, viewclip_idx) ); - mBombRef.link(static_cast<dAcBomb_c *>(ac)); + mBombRef.link(ac); dAcBomb_c *bomb = mBombRef.get(); if (bomb != nullptr) { field_0x394 = 0x3C; @@ -160,15 +164,13 @@ void dAcBombf_c::regrowBomb() { bomb->setActorProperty(AC_PROP_0x1); } if (field_0x3D4 == 0) { - bomb->field_0xA44 *= 1.5f; + bomb->mFuseTime *= 1.5f; } } } void dAcBombf_c::initializeState_Wait() {} -extern "C" u16 lbl_8057A750; - void dAcBombf_c::executeState_Wait() { if (SceneflagManager::sInstance->checkBoolFlag(mRoomID, mDespawnSceneFlag)) { deleteRequest(); @@ -194,7 +196,9 @@ void dAcBombf_c::executeState_Wait() { } else { startSound(SE_TIMESLIP_TIMESLIP_REV); } - dJEffManager_c::spawnEffect(lbl_8057A750, mPosition, nullptr, nullptr, nullptr, nullptr, 0, 0); + dJEffManager_c::spawnEffect( + PARTICLE_RESOURCE_ID_MAPPING_464_, mPosition, nullptr, nullptr, nullptr, nullptr, 0, 0 + ); } scaleFactor *= mTimeAreaStruct.field_0x00; @@ -206,14 +210,14 @@ void dAcBombf_c::executeState_Wait() { } dAcBomb_c *bomb = mBombRef.get(); if (bomb != nullptr) { - if (!bomb->mStateMgr.isState(dAcBomb_c::StateID_FlowerWait) && field_0x3D0 == 0) { + if (!bomb->mStateMgr.isState(dAcBomb_c::StateID_FlowerWait) && mIsUnderground == 0) { mBombRef.unlink(); field_0x394 = 0x3C; } } else { if (field_0x394 != 0) { field_0x394--; - } else if (field_0x3D0 == 0 || dAcPy_c::LINK->getSquareDistanceTo(mPosition) > 22500.0f) { + } else if (mIsUnderground == 0 || dAcPy_c::LINK->getSquareDistanceTo(mPosition) > 22500.0f) { regrowBomb(); } } diff --git a/src/REL/d/a/e/d_a_e_ks.cpp b/src/REL/d/a/e/d_a_e_ks.cpp index baee6dfc..e35e6123 100644 --- a/src/REL/d/a/e/d_a_e_ks.cpp +++ b/src/REL/d/a/e/d_a_e_ks.cpp @@ -187,7 +187,7 @@ void dAcEKs_c::setStartingState() { changeState(StateID_Move); mCurrentState = mStartingState; mAcch.ClrRoofNone(); - mAcch.SetField_0xD4(55.f); + mAcch.SetRoofCrrHeight(55.f); mAcch.SetGroundUpY(30.f); mAcchCir.SetWall(20.f, 60.f); } break; @@ -199,14 +199,14 @@ void dAcEKs_c::setStartingState() { } mAcch.ClrRoofHit(); mAcch.SetGroundUpY(0.f); - mAcch.SetField_0xD4(0.f); + mAcch.SetRoofCrrHeight(0.f); mAcchCir.SetWall(0.f, 5.f); } break; case EKS_STARTSTATE_PathMove: { mCurrentState = mStartingState; mAcch.ClrRoofNone(); - mAcch.SetField_0xD4(55.f); + mAcch.SetRoofCrrHeight(55.f); mAcch.SetGroundUpY(30.f); mAcchCir.SetWall(20.f, 60.f); changeState(StateID_PathMove); @@ -1789,7 +1789,7 @@ void dAcEKs_c::initializeState_Wait() { mRotation.y = field_0xD8A; mRotation.x = mAng(0); mAcch.ClrRoofHit(); - mAcch.SetField_0xD4(0); + mAcch.SetRoofCrrHeight(0); mAcch.SetGroundUpY(0); setBattleBgmRelated(0); @@ -2042,7 +2042,7 @@ void dAcEKs_c::finalizeState_WakeUp() { mAngle.y = mRotation.y; mAcch.ClrRoofNone(); mAcchCir.SetWall(20, 60); - mAcch.SetField_0xD4(55); + mAcch.SetRoofCrrHeight(55); mAcch.SetGroundUpY(30); } @@ -2116,7 +2116,7 @@ void dAcEKs_c::initializeState_WaitReady() { field_0xDA5 = 0; field_0xD50 = 30; mAcch.ClrRoofHit(); - mAcch.SetField_0xD4(0.f); + mAcch.SetRoofCrrHeight(0.f); mAcch.SetGroundUpY(0.f); field_0xDAD = 0; field_0xDAE = 0; @@ -2853,7 +2853,7 @@ void dAcEKs_c::initializeState_WindBlow() { mAcceleration = -0.5f; mAcch.ClrRoofNone(); mAcchCir.SetWall(20, 60); - mAcch.SetField_0xD4(55); + mAcch.SetRoofCrrHeight(55); mAcch.SetGroundUpY(30); } void dAcEKs_c::executeState_WindBlow() { diff --git a/src/REL/d/a/e/d_a_e_remly.cpp b/src/REL/d/a/e/d_a_e_remly.cpp index 90ad9b28..5df1fc7d 100644 --- a/src/REL/d/a/e/d_a_e_remly.cpp +++ b/src/REL/d/a/e/d_a_e_remly.cpp @@ -208,7 +208,7 @@ int dAcEremly_c::actorCreate() { field_0xA50.z = mPosition.z; mAcchCir.SetWall(mScaleF * 10.f, mScaleF * 60.f); - mAcch.SetField_0xD4(100.f + _weird_zero); + mAcch.SetRoofCrrHeight(100.f + _weird_zero); field_0xB04 = 60.f; if (mIsHorwellsPet == 0) { @@ -1113,7 +1113,7 @@ void dAcEremly_c::initializeState_Fly() { mYOffset = 0.f; mAnmStep = 0; - mAcch.SetField_0xD4(f); + mAcch.SetRoofCrrHeight(f); mVelocity.x = mVelocity.z = 0.f; mSpeed = 0.f; diff --git a/src/REL/d/a/e/d_a_e_sm.cpp b/src/REL/d/a/e/d_a_e_sm.cpp index f63d96b7..e7d89d7d 100644 --- a/src/REL/d/a/e/d_a_e_sm.cpp +++ b/src/REL/d/a/e/d_a_e_sm.cpp @@ -164,7 +164,7 @@ int dAcEsm_c::actorCreate() { mAcchCir.SetWall(mScaleTarget.y * 100.f, mScaleTarget.x * 100.f); mStts.SetRank(10); mObjAcch.SetGndThinCellingOff(); - mObjAcch.field_0x390 = 1; + mObjAcch.SetWtrChkMode(1); mMaxSpeed = -40.f; @@ -1093,8 +1093,8 @@ bool dAcEsm_c::fn_187_4B50() { if (mBombRef.isLinked()) { dAcBomb_c *pBomb = mBombRef.get(); if (pBomb) { - pBomb->On_0xA3C(0x4); - pBomb->Off_0xA3C(0x800000); + pBomb->setFlag(dAcBomb_c::FLAG_BOMB_HIT); + pBomb->unsetFlag(dAcBomb_c::FLAG_FUSE_PAUSED); mBombRef.unlink(); } diff --git a/src/REL/d/a/obj/d_a_obj_barrel.cpp b/src/REL/d/a/obj/d_a_obj_barrel.cpp index 546fab3e..9400a0d0 100644 --- a/src/REL/d/a/obj/d_a_obj_barrel.cpp +++ b/src/REL/d/a/obj/d_a_obj_barrel.cpp @@ -5,6 +5,7 @@ #include "d/a/d_a_base.h" #include "d/a/d_a_item.h" #include "d/a/d_a_player.h" +#include "d/a/e/d_a_en_base.h" #include "d/a/npc/d_a_npc_ce_friend.h" #include "d/a/npc/d_a_npc_ce_lady.h" #include "d/a/obj/d_a_obj_base.h" @@ -91,7 +92,11 @@ static dCcD_SrcCyl sSrcCyl = { { /* mObjAt */ {AT_TYPE_PHYSICS, 0x10013, {0, 0, 0}, 4, 0, 0, 0, 0, 0}, /* mObjTg */ - {~(AT_TYPE_BUGNET | AT_TYPE_BEETLE | AT_TYPE_GLITTERING_SPORES | AT_TYPE_0x8000), 0x2000111, {0, 0xF, 0x407}, 0, 0}, + {~(AT_TYPE_BUGNET | AT_TYPE_BEETLE | AT_TYPE_GLITTERING_SPORES | AT_TYPE_0x8000), + 0x2000111, + {0, 0xF, 0x407}, + 0, + 0}, /* mObjCo*/ {0xE9}, }, { @@ -1067,7 +1072,6 @@ void dAcOBarrel_c::fn_293_3DB0() { quat_0xD90 = q1 * q2 * q0 * quat_0xD90; } -extern "C" void fn_800307E0(const mVec3_c &, s32); void dAcOBarrel_c::fn_293_4200() { getLinkage().forceRemove(this); @@ -1124,7 +1128,7 @@ void dAcOBarrel_c::fn_293_4200() { PARTICLE_RESOURCE_ID_MAPPING_658_, emitPosition, nullptr, &mScale, nullptr, nullptr, 0, 0 ); } - fn_800307E0(mPosition, 0); + dAcEnBase_c::fn_800307E0(&mPosition, 0); startSound(SE_Barrel_BOMB); mStateMgr.changeState(StateID_Explode); diff --git a/src/REL/d/a/obj/d_a_obj_tubo.cpp b/src/REL/d/a/obj/d_a_obj_tubo.cpp index c204164b..91607903 100644 --- a/src/REL/d/a/obj/d_a_obj_tubo.cpp +++ b/src/REL/d/a/obj/d_a_obj_tubo.cpp @@ -320,7 +320,7 @@ void dAcOtubo_c::finalizeState_Grab() { mSph.OnAtSet(); } mObjAcch.ClrRoofNone(); - mObjAcch.field_0x0D4 = 50.f; + mObjAcch.SetRoofCrrHeight(50.f); } void dAcOtubo_c::initializeState_Put() {} diff --git a/src/REL/d/t/d_t_action.cpp b/src/REL/d/t/d_t_action.cpp index a40bbacb..5ea4bf52 100644 --- a/src/REL/d/t/d_t_action.cpp +++ b/src/REL/d/t/d_t_action.cpp @@ -52,7 +52,7 @@ int dTgAction_c::actorExecute() { } if (pObj->mProfileName == fProfile::BOMB) { if (checkAreaBox(mActiveMtx, pObj->getPosition())) { - reinterpret_cast<dAcBomb_c *>(pObj)->On_0xA3C(0x20000000); + reinterpret_cast<dAcBomb_c *>(pObj)->setFlag(dAcBomb_c::FLAG_0x20000000); } } } diff --git a/src/d/a/d_a_item.cpp b/src/d/a/d_a_item.cpp index 3de0f79f..1606c315 100644 --- a/src/d/a/d_a_item.cpp +++ b/src/d/a/d_a_item.cpp @@ -774,7 +774,7 @@ int dAcItem_c::create() { getItemFlagStruct(getItemId())->field_0x01 * 0.5f, getItemFlagStruct(getItemId())->field_0x00 * 0.6f ); mObjAcch.Set(this, 1, &mAcchCir); - mObjAcch.field_0x0D4 = 50.0f; + mObjAcch.SetRoofCrrHeight(50.0f); mObjAcch.SetClrSpeedY(); mObjAcch.SetField_0xC(4); mAcceleration = -2.0f; diff --git a/src/d/a/d_a_player.cpp b/src/d/a/d_a_player.cpp index acffedc2..367db7e2 100644 --- a/src/d/a/d_a_player.cpp +++ b/src/d/a/d_a_player.cpp @@ -1,5 +1,15 @@ #include "d/a/d_a_player.h" +#include "common.h" +#include "d/a/d_a_base.h" +#include "d/a/obj/d_a_obj_base.h" +#include "d/a/obj/d_a_obj_bomb.h" +#include "f/f_profile.h" +#include "f/f_profile_name.h" +#include "toBeSorted/minigame_mgr.h" + +#include <stddef.h> + dAcPy_c *dAcPy_c::LINK; // TODO: Disable this pragma when the ctors are matching @@ -8,3 +18,136 @@ dAcPy_c::dAcPy_c() {} #pragma dont_inline reset dAcPy_c::~dAcPy_c() {} + +namespace { +bool isProfile(dAcBase_c *pActor, ProfileName profile) { + return pActor && pActor->mProfileName == profile; +} +} // namespace + +bool dAcPy_c::ObjectArray::insert(dAcObjBase_c *pObj) { + for (size_t i = 0; i < sNumObjects; ++i) { + if (mObjs[i].get() != pObj) { + continue; + } + + if (isProfile(pObj, fProfile::BOMB)) { + mCounter[i] = MAX(0, static_cast<dAcBomb_c *>(pObj)->getFuseTimer()) + 3; + } else { + mCounter[i] = 90; + } + return true; + } + + for (size_t i = 0; i < sNumObjects; ++i) { + if (mObjs[i].get() != nullptr) { + continue; + } + + mObjs[i].link(pObj); + + if (isProfile(pObj, fProfile::BOMB)) { + mCounter[i] = MAX(0, static_cast<dAcBomb_c *>(pObj)->getFuseTimer()) + 3; + } else { + mCounter[i] = 90; + } + return true; + } + + return false; +} + +void dAcPy_c::ObjectArray::execute() { + // Unlink Object as needed + for (int i = 0; i < sNumObjects; ++i) { + dAcObjBase_c *pObj = mObjs[i].get(); + if (isProfile(pObj, fProfile::BOMB)) { + if (static_cast<dAcBomb_c *>(pObj)->isState(dAcBomb_c::StateID_Explode)) { + mObjs[i].unlink(); + mCounter[i] = 0; + } + } else { + if (--mCounter[i] == 0) { + mObjs[i].unlink(); + } + } + } + + // Try to bubble objects left + // This seems buggy if multiple objects arent link consecutively + int lastOccupiedObject = sNumObjects; + for (int i = sNumObjects - 1; i >= 0; --i) { + // Skip Occupied objects + if (mObjs[i].isLinked()) { + lastOccupiedObject = i; + continue; + } + + if (lastOccupiedObject != sNumObjects) { + mObjs[i].link(mObjs[lastOccupiedObject].get()); + mCounter[i] = mCounter[lastOccupiedObject]; + mObjs[lastOccupiedObject].unlink(); + + lastOccupiedObject = sNumObjects; + } + } +} + +dAcObjBase_c *dAcPy_c::ObjectArray::get(s32 index) { + if (index >= sNumObjects) { + return nullptr; + } + + return mObjs[index].get(); +} + +void dAcPy_c::ObjectArray::removeBombs() { + for (int i = 0; i < sNumObjects; ++i) { + dAcObjBase_c *pObj = get(i); + if (pObj != nullptr) { + if (pObj->mProfileName == fProfile::BOMB) { + dAcBomb_c *pBomb = static_cast<dAcBomb_c *>(pObj); + pBomb->deleteRequest(); + pBomb->mEffect1.remove(true); + pBomb->mEffect2.remove(true); + } + } + } +} + +bool dAcPy_c::isInMinigameInsectCapture() { + return MinigameManager::GetInstance()->checkInInsectCapture(); +} +bool dAcPy_c::isInMinigamePumpkinCarry() { + return MinigameManager::GetInstance()->checkInPumpkinCarry(); +} +bool dAcPy_c::isInMinigameBambooCutting() { + return MinigameManager::GetInstance()->checkInBambooCutting(); +} +bool dAcPy_c::isInMinigameThrillDigger() { + return MinigameManager::GetInstance()->checkInThrillDigger(); +} +bool dAcPy_c::isInMinigameFunFunIsland() { + return MinigameManager::GetInstance()->checkInFunFunIsland(); +} +bool dAcPy_c::isInMinigameHouseCleaning() { + return MinigameManager::GetInstance()->checkInHouseCleaning(); +} +bool dAcPy_c::isInMinigameTrialTimeAttack() { + return MinigameManager::GetInstance()->checkInTrialTimeAttack(); +} +bool dAcPy_c::isInMinigameBossRush() { + return MinigameManager::GetInstance()->checkInBossRush(); +} +bool dAcPy_c::isInMinigamePumpkinArchery() { + return MinigameManager::GetInstance()->checkInPumpkinArchery(); +} +bool dAcPy_c::isInMinigameHarpPlaying() { + return MinigameManager::GetInstance()->checkInHarpPlaying(); +} +bool dAcPy_c::isInMinigameRollerCoaster() { + return MinigameManager::GetInstance()->checkInRollerCoaster(); +} +bool dAcPy_c::isInMinigameSprialChargeTutorial() { + return MinigameManager::GetInstance()->checkInSprialChargeTutorial(); +} diff --git a/src/d/a/obj/d_a_obj_bomb.cpp b/src/d/a/obj/d_a_obj_bomb.cpp index 5b9d6b6f..2550062d 100644 --- a/src/d/a/obj/d_a_obj_bomb.cpp +++ b/src/d/a/obj/d_a_obj_bomb.cpp @@ -1,20 +1,1258 @@ #include "d/a/obj/d_a_obj_bomb.h" +#include "c/c_lib.h" +#include "c/c_math.h" +#include "common.h" +#include "d/a/d_a_base.h" +#include "d/a/d_a_player.h" +#include "d/a/e/d_a_en_base.h" +#include "d/a/obj/d_a_obj_base.h" +#include "d/col/bg/d_bg_pc.h" +#include "d/col/bg/d_bg_s.h" +#include "d/col/bg/d_bg_s_gnd_chk.h" +#include "d/col/c/c_cc_d.h" +#include "d/col/c/c_m3d.h" +#include "d/col/c/c_m3d_g_pla.h" +#include "d/col/cc/d_cc_s.h" +#include "d/d_light_env.h" +#include "d/d_linkage.h" +#include "d/d_rumble.h" +#include "d/d_sc_game.h" +#include "d/d_stage_mgr.h" +#include "d/d_vec.h" +#include "d/snd/d_snd_wzsound.h" +#include "d/t/d_t_stream.h" #include "f/f_base.h" #include "f/f_profile.h" #include "f/f_profile_name.h" +#include "m/m3d/m3d.h" +#include "m/m_angle.h" +#include "m/m_color.h" +#include "m/m_mtx.h" +#include "m/m_quat.h" +#include "m/m_vec.h" +#include "nw4r/g3d/res/g3d_resfile.h" +#include "nw4r/g3d/res/g3d_resmdl.h" +#include "nw4r/math/math_arithmetic.h" +#include "nw4r/math/math_types.h" +#include "rvl/GX/GXTypes.h" +#include "rvl/MTX/mtx.h" +#include "s/s_Math.h" #include "s/s_State.hpp" +#include "toBeSorted/attention.h" +#include "toBeSorted/d_emitter.h" +#include "toBeSorted/event_manager.h" +#include "toBeSorted/minigame_mgr.h" SPECIAL_ACTOR_PROFILE(BOMB, dAcBomb_c, fProfile::BOMB, 0x128, 0, 2); +static const Vec sSmokeOffset = {0, 60, 0}; + +struct dAcBomc_HIO_c { + static const f32 getBBoxX() { + return 36.0f; + } + static const f32 getBBoxY() { + return 66.0f; + } + static const f32 getBBoxZ() { + return 5.0f; + } + static const f32 getBombScale() { + return 30.0f; + } + static const s32 getSomething() { + return 40; + } + static const mVec3_c getBBoxMin() { + return mVec3_c(-bbox_x, 0.0f, -bbox_x); + } + static const mVec3_c getBBoxMax() { + return mVec3_c(bbox_x, bbox_y, bbox_x); + } + static const f32 bbox_x, bbox_y, bbox_z; +}; +static dAcBomc_HIO_c sHIO = {}; + +const f32 dAcBomc_HIO_c::bbox_x = sHIO.getBBoxX(); +const f32 dAcBomc_HIO_c::bbox_y = sHIO.getBBoxY(); +const f32 dAcBomc_HIO_c::bbox_z = sHIO.getBBoxZ(); + STATE_DEFINE(dAcBomb_c, Wait); STATE_DEFINE(dAcBomb_c, FlowerWait); STATE_DEFINE(dAcBomb_c, Explode); STATE_DEFINE(dAcBomb_c, Carry); STATE_DEFINE(dAcBomb_c, WindCarry); -bool dAcBomb_c::createHeap() {} +dCcD_SrcSph sSphSrc = { + /* mObjInf */ + {/* mObjAt */ {AT_TYPE_BOMB, 0x1803E, {0, 0, 0}, sHIO.getSomething(), 0, 0, 0, 0, 0}, + /* mObjTg */ + {~(AT_TYPE_BUGNET | AT_TYPE_GLITTERING_SPORES | AT_TYPE_0x8000 | AT_TYPE_0x10), 0x800111, {0, 0x0A, 0x40F}, 0, 0}, + /* mObjCo */ {0xE9}}, + /* mSphInf */ + {sHIO.getBombScale()} +}; + +void dAcBomb_c::coHitCallback(cCcD_Obj *i_objInfB) { + if (!i_objInfB->ChkCo_0x8000()) { + return; + } + + setFlag(dAcBomb_c::FLAG_BOMB_HIT); + setActorProperty(AC_PROP_0x4); +} + +bool dAcBomb_coHitCallback(dAcObjBase_c *i_actorA, cCcD_Obj *i_objInfA, dAcObjBase_c *i_actorB, cCcD_Obj *i_objInfB) { + static_cast<dAcBomb_c *>(i_actorA)->coHitCallback(i_objInfB); + return true; +} + +void dAcBomb_c::tgHitCallback(dAcObjBase_c *i_actorB, cCcD_Obj *i_objInfA, cCcD_Obj *i_objInfB) { + // Check if it is being blown + if ((i_objInfB->ChkAtType(AT_TYPE_WIND | AT_TYPE_BELLOWS) && i_objInfB->GetAtSrcModifier() == AT_MOD_WIND) && + !(i_actorB && + (i_actorB->mProfileName == fProfile::OBJ_WIND || i_actorB->mProfileName == fProfile::OBJ_TORNADO))) { + if (!getLinkage().checkState(dLinkage_c::STATE_ACTIVE) && !checkFlag(dAcBomb_c::FLAG_BOMB_HIT)) { + if (!(isState(StateID_FlowerWait) || isState(StateID_Explode))) { + cLib::addCalcPosXZ(&mHitForce, i_objInfA->GetTgAtHitDir() * 0.5f, 0.5f, 10.0f, 1.0f); + setFlag(dAcBomb_c::FLAG_0x8000); + } + } + } else if (!i_objInfB->ChkAtType(AT_TYPE_0x40 | AT_TYPE_WIND | AT_TYPE_WHIP | AT_TYPE_BEETLE) || + i_objInfB->ChkAt_0x4000()) { + if (i_objInfB->ChkAtType(AT_TYPE_0x20000)) { + if (isState(StateID_FlowerWait)) { + changeState(StateID_Wait); + dAcPy_c::insertOwnedObject(this); + } + + const dAcPy_c *pPlayer = dAcPy_c::GetLink2(); + + mVec3_c target; + setXYZCirclePoint(target, pPlayer->mRotation.y, 30.0f, 0.0f); + rollTo(target); + } else if (i_objInfB->ChkAtType( + AT_TYPE_SWORD | AT_TYPE_0x40 | AT_TYPE_SLINGSHOT | AT_TYPE_0x20000 | AT_TYPE_BEETLE + ) && + checkFlag(dAcBomb_c::FLAG_FLOWER | dAcBomb_c::FLAG_0x400000)) { + unsetFlag(dAcBomb_c::FLAG_FLOWER); + setFlag(dAcBomb_c::FLAG_0x400000); + unsetActorProperty(AC_PROP_0x1); + if (isState(StateID_FlowerWait)) { + dAcPy_c::insertOwnedObject(this); + } + if (!checkFlag(dAcBomb_c::FLAG_0x100) && i_objInfB->ChkAtType(AT_TYPE_SWORD)) { + setFlag(dAcBomb_c::FLAG_0x100); + } + } else { + setFlag(dAcBomb_c::FLAG_BOMB_HIT); + setActorProperty(AC_PROP_0x4); + if (i_objInfB->ChkAtType(AT_TYPE_BOMB)) { + setFlag(dAcBomb_c::FLAG_CHAIN_BOMB); + } + } + } +} + +bool dAcBomb_tgHitCallback(dAcObjBase_c *i_actorA, cCcD_Obj *i_objInfA, dAcObjBase_c *i_actorB, cCcD_Obj *i_objInfB) { + static_cast<dAcBomb_c *>(i_actorA)->tgHitCallback(i_actorB, i_objInfA, i_objInfB); + return true; +} + +bool dAcBomb_c::createHeap() { + mRes = nw4r::g3d::ResFile(getOarcResFile("Alink")); + + nw4r::g3d::ResMdl mdl = mRes.GetResMdl("EquipBomb"); + bool result = mMdl.create(mdl, &mAllocator, 0x120); + if (!result) { + return false; + } + + mMainMatID = m3d::getMatID(mdl, "m_Main"); + + if (getBombType() == BOMBF_CRAWLSPACE) { + mMdl.setPriorityDraw(0x82, 0x7F); + } + return result; +} int dAcBomb_c::create() { + CREATE_ALLOCATOR(dAcBomb_c); + + mAcch.Set(this, 1, &mAcchCir); + mAcch.SetRoofCrrHeight(60.0f); + mAcch.SetGndChkOffset(60.0f); + mAcch.GetRoof().SetField_0x7C(1); + mAcch.SetWaterCheckOffset(10000.0f); + mAcch.SetWtrChkMode(2); + mAcch.ClrWaterNone(); + mAcch.ClrRoofNone(); + mAcch.OnLineCheck(); + + mAcchCir.SetWall(30.0f, 30.0f); + + if (getBombType() == BOMBF_CRAWLSPACE) { + mStts.SetRank(4); + } else { + mStts.SetRank(5); + } + + mSph.Set(sSphSrc); + mSph.SetStts(mStts); + mSph.SetTgCallback(dAcBomb_tgHitCallback); + mSph.setCenter(mPosition); + + MTXIdentity(mMtx); + + mBoundingBox.Set(sHIO.getBBoxMin(), sHIO.getBBoxMax()); + + mAcceleration = dAcPy_c::getBombAcceleration(); + mMaxSpeed = dAcPy_c::getBombMaxSpeed(); + + mFuseTime = dAcPy_c::getBombExplodeTimer(); + + mLinkage.set(0xc9c2, 25.0f, 43.0f, 36.0f, nullptr); + mLinkage.setField_0x8C_0x90(dAcPy_c::getBombUnknown0_0(), dAcPy_c::getBombUnknown0_1()); + mLinkage.setField_0x94_0x98(dAcPy_c::getBombUnknown1_0(), dAcPy_c::getBombUnknown1_1()); + field_0xA50 = 1.0f; + mVec3_c pos = (mPosition); + mAcch.CrrPos(*dBgS::GetInstance()); + setRoomId(); + + switch (getBombType()) { + case BOMB_0: + case BOMB_4: + case BOMB_EXPLODE_NO_DAMAGE: { + changeState(StateID_Explode); + } break; + case BOMB_PLAYER_CARRY: { + setFlag(dAcBomb_c::FLAG_0x200000); + setFlag(dAcBomb_c::FLAG_PLAYER_MAKE); + if (checkWaterIn()) { + setFlag(dAcBomb_c::FLAG_UNDERWATER); + mAcceleration = dAcPy_c::getBombAcceleration_1(); + mMaxSpeed = dAcPy_c::getBombMaxSpeed_1(); + } + changeState(StateID_Carry); + } break; + case BOMB_BOCO_CARRY: { + setFlag(dAcBomb_c::FLAG_BOKO_CARRY); + changeState(StateID_Carry); + } break; + case BOMBF: + case BOMBF_CRAWLSPACE: + case BOMB_5: { + mPosition = pos; + changeState(StateID_FlowerWait); + } break; + default: { + changeState(StateID_Wait); + } break; + } + + f32 yOffset = mScale.y * 25.0f; + mWorldMtx.transS(mPosition); + mWorldMtx.ZXYrotM(mRotation); + mMtx_c m0, m1; + + m0.transS(0, yOffset, 0); + mWorldMtx.concat(m0); + + mWorldMtx.concat(mMtx); + + m1.transS(0, -yOffset, 0); + mWorldMtx.concat(m1); + + mMdl.setLocalMtx(mWorldMtx); + + setBombColor(); + mMdl.calc(false); + setSmokePos(); + mExternalTranslation = mPosition; + + return SUCCEEDED; +} + +void dAcBomb_c::unkVirtFunc_0x5C() { + if (isState(StateID_Wait)) { + deleteRequest(); + mEffect1.remove(true); + mEffect2.remove(true); + } +} + +int dAcBomb_c::doDelete() { + mLinkage.forceRemove(this); + return SUCCEEDED; +} + +// NONMATCHING +bool dAcBomb_c::checkExplode() { + if (mCarryTimer != 0) { + mCarryTimer--; + } + + if (mFuseTime > 0) { + bool b = !checkFlag( + dAcBomb_c::FLAG_FLOWER | dAcBomb_c::FLAG_0x200000 | dAcBomb_c::FLAG_FALL_IN_WATER | + dAcBomb_c::FLAG_NEAR_TIMEDOOR + ) && + !isState(StateID_Explode); + if (b) { + mFuseTime--; + if (checkFlag(dAcBomb_c::FLAG_BOKO_CARRY | dAcBomb_c::FLAG_FUSE_PAUSED)) { + s16 explodeTimer = dAcPy_c::getBombExplodeTimer(); + if (mFuseTime == (explodeTimer >> 1) || mFuseTime == (explodeTimer >> 2) || + mFuseTime == (explodeTimer >> 3) || mFuseTime == (explodeTimer >> 4)) { + mFuseTime <<= 1; + } + } + } + } + + if (checkFlag(dAcBomb_c::FLAG_FUSE_PAUSED | dAcBomb_c::FLAG_FALL_IN_WATER | dAcBomb_c::FLAG_NEAR_TIMEDOOR)) { + return false; + } + + if (mFuseTime == 0 || checkFlag(dAcBomb_c::FLAG_BOMB_HIT) || + (mSph.ChkCoHit() && mSph.GetCoActor()->isActorPlayer() && + static_cast<dAcPy_c *>(mSph.GetCoActor())->isBurning()) || + (checkFlag(dAcBomb_c::FLAG_BEETLE_CARRY) && mCarryTimer == 0) && + ( // Check Beetle or Chu grab + (mSph.ChkCoHit() && mSph.GetCoActor()->mProfileName != fProfile::BOOMERANG && + mSph.GetCoActor()->mProfileName != fProfile::E_SM) || + !mAcch.fn_80340ca0(mUnkInfo) + )) { + changeState(StateID_Explode); + return true; + } + + if (mAcch.ChkGndHit()) { + const dBgS_GndChk &gnd = mAcch.GetGnd(); + if (dBgS::GetInstance()->GetSpecialCode(gnd) == POLY_ATTR_LAVA || + dBgS::GetInstance()->GetGroundCode(gnd) == 4 /* FIXME*/) { + mUnkInfo.SetPolyInfo(mAcch.GetGnd()); + changeState(StateID_Explode); + return true; + } + } + + if (mAcch.ChkWallHit(nullptr)) { + if (dBgS::GetInstance()->GetSpecialCode(mAcchCir) == POLY_ATTR_LAVA) { + mUnkInfo.SetPolyInfo(mAcchCir); + changeState(StateID_Explode); + return true; + } + } + + return false; +} + +void dAcBomb_c::setRoomId() { + if (mAcch.GetGroundH() != -1e9f) { + mRoomID = dBgS::GetInstance()->GetRoomId(mAcch.GetGnd()); + } else if (mRoomID == -1) { + mRoomID = dAcPy_c::GetLink2()->getRoomId(); + } +} + +void dAcBomb_c::setSmokePos() { + mVec3_c in = sSmokeOffset; + mWorldMtx.multVec(in, mSmokePosNext); + mSmokePos = (mSmokePosNext - mSmokePosPrev) * 0.5f; +} + +bool dAcBomb_c::checkWaterIn() { + return checkFlag(dAcBomb_c::FLAG_0x20000000) || + (mAcch.ChkWaterHit() && (mPosition.y + mScale.x * sHIO.getBombScale() < mAcch.GetWtrGroundH())); +} + +void dAcBomb_c::setTransformFromFlower(const mMtx_c &m) { + if (mLinkage.checkState(dLinkage_c::STATE_ACTIVE)) { + return; + } + mMtx = m; + + mMtx_c &m0 = mMtx; + mVec3_c out; + m0.setTranslation(mVec3_c::Zero); + m0.multVecSR(mVec3_c::Ey, out); + + f32 f = field_0xA50 * (25.0f * mScale.y); + m.getTranslation(mExternalTranslation); + + mPosition = mExternalTranslation + out * f; + mPosition.y -= f; +} + +void dAcBomb_c::setPickupTarget() { + if (checkFlag(dAcBomb_c::FLAG_FALL_IN_WATER)) { + return; + } + + AttentionManager::GetInstance()->addPickUpTarget(*this, 120.0f); +} + +void dAcBomb_c::lookAt() { + dAcPy_c::GetLink2()->lookTowardItem(mPositionCopy2, 4, 0x5555, 300, 400, -400); +} + +void dAcBomb_c::bounceWall(mAng angle) { + mSpeed *= dAcPy_c::getBombBounceSpeed(); + mRollSpeed *= dAcPy_c::getBombBounceSpeed(); + + mAngle.y = angle - mAng((mAngle.y + 0x8000) - angle); + mRollRotationY = angle - mAng((mRollRotationY + 0x8000) - angle); +} + +void dAcBomb_c::getVelocity(mVec3_c &out) { + // out = Bomb Speed (Standard Parameters) + setXYZCirclePoint(out, mAngle.y, mSpeed, mVelocity.y); + + if (mRollFrameTimer != 0) { + f32 f = cM::minMaxLimit(mRollFrameTimer * 0.02f, 0.0f, 1.0f); + mVec3_c v; + setXYZCirclePoint(v, mRollRotationY, mRollSpeed, 0.0f); + + out = out * (1.0f - f) + v * f; + } +} + +void dAcBomb_c::initializeState_Explode() { + setActorProperty(AC_PROP_0x4); + + dAcPy_c *pPlayer = dAcPy_c::GetLink2(); + + dAcObjBase_c *pObj = pPlayer->getBeetleHeldActor(); + if (pObj == this) { + mLinkage.forceRemove(this); + pPlayer->setBeetleReleasedObject(this); + } + + mRotation.y = cM::rndF(65536); + mSmokePos = mVec3_c::Zero; + mVec3_c out; + if (getOldStateID() == StateID_FlowerWait || dBgS::GetInstance()->ChkPolySafe(mUnkInfo)) { + if (getOldStateID() == StateID_FlowerWait) { + mWorldMtx.multVecSR(mVec3_c::Ey, out); + } else { + cM3dGPla plane; + dBgS::GetInstance()->GetTriPla(mUnkInfo, &plane); + out = plane.GetN(); + } + (void)out.atan2sX_Z(); + (void)cM::atan2s(out.absXZ(), out.y); + + mPosition.y += 25.0f; + + mPosition -= out * 25.0f; + + } else if (mAcch.ChkGndHit()) { + cM3dGPla plane; + dBgS::GetInstance()->GetTriPla(mAcch.GetGnd(), &plane); + + (void)plane.GetN().atan2sX_Z(); + (void)cM::atan2s(plane.GetN().absXZ(), plane.GetN().y); + } + + dCamera_c *pCam = dScGame_c::getCamera(); + mVec3_c v = pCam->getTarget() - pCam->getPosition(); + if (v.getSquareMag() > 0.01f) { + v.normalize(); + } else { + v = mVec3_c::Ez; + } + + cM3dGPla plane; + plane.SetupNP(v, pCam->getPosition()); + + f32 d = cM3d_SignedLenPlaAndPos(&plane, mPosition); + + mVec3_c temp(dAcPy_c::getBombParticleScale(), dAcPy_c::getBombParticleScale(), dAcPy_c::getBombParticleScale()); + if (d < dAcPy_c::getBombDistanceUnknown0()) { + dEmitterBase_c *pEmitter = dJEffManager_c::spawnEffect( + PARTICLE_RESOURCE_ID_MAPPING_322_, mPosition, nullptr, &temp, nullptr, nullptr, 0, 0 + ); + if (pEmitter != nullptr) { + pEmitter->setRate(10.0f); + } + (void)dJEffManager_c::spawnEffect( + PARTICLE_RESOURCE_ID_MAPPING_323_, mPosition, nullptr, &temp, nullptr, nullptr, 0, 0 + ); + pEmitter = dJEffManager_c::spawnEffect( + PARTICLE_RESOURCE_ID_MAPPING_324_, mPosition, nullptr, &temp, nullptr, nullptr, 0, 0 + ); + if (pEmitter != nullptr) { + pEmitter->setRate(5.0f); + } + } else if (checkFlag(dAcBomb_c::FLAG_CHAIN_BOMB)) { + (void)dJEffManager_c::spawnEffect( + PARTICLE_RESOURCE_ID_MAPPING_321_, mPosition, nullptr, &temp, nullptr, nullptr, 0, 0 + ); + } else { + (void)dJEffManager_c::spawnEffect( + PARTICLE_RESOURCE_ID_MAPPING_322_, mPosition, nullptr, &temp, nullptr, nullptr, 0, 0 + ); + (void)dJEffManager_c::spawnEffect( + PARTICLE_RESOURCE_ID_MAPPING_323_, mPosition, nullptr, &temp, nullptr, nullptr, 0, 0 + ); + (void)dJEffManager_c::spawnEffect( + PARTICLE_RESOURCE_ID_MAPPING_324_, mPosition, nullptr, &temp, nullptr, nullptr, 0, 0 + ); + (void)dJEffManager_c::spawnEffect( + PARTICLE_RESOURCE_ID_MAPPING_325_, mPosition, nullptr, &temp, nullptr, nullptr, 0, 0 + ); + } + + if (dStageMgr_c::GetInstance()->isInLastBoss() && mAcch.ChkGndHit()) { + (void)dJEffManager_c::spawnEffect( + PARTICLE_RESOURCE_ID_MAPPING_849_, mPosition, nullptr, nullptr, nullptr, nullptr, 0, 0 + ); + } + dLightEnv_c::GetPInstance()->SordFlush_set(&mPosition, 5); + + mSpeed = 0.0f; + mVelocity = mVec3_c::Zero; + mAcceleration = 0.0f; + + mSph.ClrTgSet(); + mSph.ClrCoSet(); + if (getBombType() == BOMB_EXPLODE_NO_DAMAGE) { + mSph.ClrAtSet(); + } else { + mSph.OnAtSet(); + } + + if (getBombType() == BOMBF_CRAWLSPACE) { + mSph.SetR(200.0f); + } else { + mSph.SetR(dAcPy_c::getBombExplodeRadius()); + } + + mSph.SetC(mPosition); + mSph.SetAtType(AT_TYPE_BOMB); + mSph.SetAtVec(mVec3_c::Zero); + dCcS::GetInstance()->Set(&mSph); + dCcS::GetInstance()->SetMass(&mSph, 1); + + startSound(SE_BM_EXPLODE); + mLinkage.forceRemove(this); + unsetObjectProperty(OBJ_PROP_0x1000); + mFuseTime = 0; + + f32 dist = mPosition.squareDistance(pPlayer->mPosition); + if (dist < 160000.0f) { + dRumble_c::start(dRumble_c::sRumblePreset3, dRumble_c::FLAG_SLOT0 | dRumble_c::FLAG_ACTIVE); + } else if (dist < 640000.0f) { + dRumble_c::start(dRumble_c::sRumblePreset1, dRumble_c::FLAG_SLOT0 | dRumble_c::FLAG_ACTIVE); + } + + dLightEnv_c::GetPInstance()->setBPM8_Type10_2(&mPosition); + dAcEnBase_c::fn_800307E0(&mPosition, 0); +} +void dAcBomb_c::executeState_Explode() { + if (--mFuseTime >= -3) { + dCcS::GetInstance()->Set(&mSph); + dCcS::GetInstance()->SetMass(&mSph, 1); + } else { + deleteRequest(); + } +} +void dAcBomb_c::finalizeState_Explode() {} + +void dAcBomb_c::initializeState_Carry() { + unsetFlag(dAcBomb_c::FLAG_BEETLE_CARRY | dAcBomb_c::FLAG_0x80000 | dAcBomb_c::FLAG_ROLL | dAcBomb_c::FLAG_0x10000); + mHitForce = mVec3_c::Zero; + if (mLinkage.checkConnection(dLinkage_c::CONNECTION_5)) { + setFlag(dAcBomb_c::FLAG_BEETLE_CARRY); + mCarryTimer = 5; + mLinkage.offFlag(0x20000000); + } else { + dAcBase_c *pObj = mLinkage.getControllingActor(); + if (pObj != nullptr && pObj->isActorPlayer()) { + dAcPy_c::GetLink2()->getOwnedObjects().insert(this); + } + mSph.ClrCoSet(); + } + dAcBase_c *pObj = mLinkage.getControllingActor(); + if (pObj != nullptr && pObj->mProfileName == fProfile::E_SM) { + onSoundSourceFlag(1); + } + + mSpeed = 0.0f; + mVelocity = mVec3_c::Zero; + + mLinkage.bushTpFunc(mAcch); + setRoomId(); +} +void dAcBomb_c::executeState_Carry() { + dAcPy_c *pPlayer = dAcPy_c::GetLink2(); + + if (checkExplode()) { + unsetFlag(dAcBomb_c::FLAG_BOKO_CARRY | dAcBomb_c::FLAG_FLOWER | dAcBomb_c::FLAG_0x200000); + } else { + if (!mLinkage.checkState(dLinkage_c::STATE_ACTIVE)) { + if (checkFlag(dAcBomb_c::FLAG_0x100000)) { + unsetFlag(dAcBomb_c::FLAG_0x100000); + mMtx.ZrotS(-mRotation.z); + mMtx.XrotM(-mRotation.x); + mMtx.YrotM(-mRotation.y); + mMtx.concat(mWorldMtx); + mMtx.m[0][3] = 0.0f; + mMtx.m[1][3] = 0.0f; + mMtx.m[2][3] = 0.0f; + } + if (mLinkage.checkState(dLinkage_c::STATE_3)) { + setFlag(dAcBomb_c::FLAG_0x80000 | dAcBomb_c::FLAG_ROLL); + mRollRotationY = pPlayer->mRotation.y; + mRollSpeed = mSpeed; + mRollFrameTimer = 60; + } + unsetFlag(dAcBomb_c::FLAG_BOKO_CARRY | dAcBomb_c::FLAG_FLOWER | dAcBomb_c::FLAG_0x200000); + changeState(StateID_Wait); + } else if (!mLinkage.checkConnection(dLinkage_c::CONNECTION_5)) { + unsetFlag(dAcBomb_c::FLAG_BEETLE_CARRY | dAcBomb_c::FLAG_FLOWER); + } + mLinkage.bushTpFunc(mAcch); + setRoomId(); + if (isState(StateID_Carry)) { + mSpeed = 0.0f; + mVelocity = mVec3_c::Zero; + } + } +} +void dAcBomb_c::finalizeState_Carry() { + if (getNewStateID() != StateID_Explode) { + offSoundSourceFlag(1); + } +} + +void dAcBomb_c::initializeState_Wait() { + mSph.OnCoSet(); + mSph.SetCoCallback(dAcBomb_coHitCallback); + field_0xA42 = 5; + if (checkFlag(dAcBomb_c::FLAG_0x4000000)) { + unsetFlag(dAcBomb_c::FLAG_0x4000000); + setFlag(dAcBomb_c::FLAG_BEETLE_CARRY); + } +} +// NONMATCHING +void dAcBomb_c::executeState_Wait() { + if (checkExplode()) { + return; + } + + if (mLinkage.checkState(dLinkage_c::STATE_ACTIVE)) { + changeState(StateID_Carry); + return; + } + + if (mUnkRef.fn_80051780(mSph)) { + changeState(StateID_WindCarry); + return; + } + + if (field_0xA42 != 0) { + field_0xA42--; + } + + mVec3_c bombVelocity; + getVelocity(bombVelocity); + + s16 bombAngleY = bombVelocity.atan2sX_Z(); + f32 bombSpeed = bombVelocity.absXZ(); + + mAng gndAngle; + + if (mAcch.ChkGndHit()) { + gndAngle = mAcch.GetGnd().GetAngle(bombAngleY); + mVelocity.y -= bombSpeed * nw4r::math::FAbs(gndAngle.sin()); + + bombVelocity *= gndAngle.cos(); + + if (mRollFrameTimer != 0) { + mRollFrameTimer--; + } + } else { + gndAngle = 0; + } + + f32 prevAccel = mAcceleration; + mVelocity.y = nw4r::ut::Max(mVelocity.y + mAcceleration, mMaxSpeed); + bombVelocity.y = mVelocity.y; + mPosition += bombVelocity; + mPosition += mStts.GetCcMove(); + + if (checkFlag(dAcBomb_c::FLAG_0x10000) && checkFlag(dAcBomb_c::FLAG_UNDERWATER) && mAcch.ChkWaterHit()) { + if (mPosition.y + (mScale.x * sHIO.getBombScale()) + 1.0f >= mAcch.GetWtrGroundH()) { + mPosition.y = mAcch.GetWtrGroundH() - (mScale.x * sHIO.getBombScale()) - 1.0f; + mVelocity.y = 0.0f; + } + } + mAcceleration = prevAccel; + f32 prevVelocityY = mVelocity.y; + s16 a0 = 0; + s16 a1 = 0; + f32 f = 1.0f; + if (mAcch.ChkGndHit() && mHitForce.squareMagXZ() > 1.0f) { + cM3dGPla plane; + dBgS::GetInstance()->GetTriPla(mAcch.GetGnd(), &plane); + + f = plane.GetAngle(mHitForce.atan2sX_Z()).cos(); + f *= f; + } + + mPosition += (mHitForce * f) + mStreamForce; + mAcch.CrrPos(*dBgS::GetInstance()); + f32 sinkTarget = 0.0f; + f32 sinkRate = 4.0f; + mVec3_c force = mVec3_c::Zero; + f32 sinkValue = mYOffset; + if (mAcch.ChkGndHit() && !mLinkage.checkState(dLinkage_c::STATE_ACTIVE)) { + s32 attr = dBgS::GetInstance()->GetSpecialCode(mAcch.mGnd); + if (attr == POLY_ATTR_CURSED_WATER) { + sinkTarget = -60.0f; + if (sinkValue >= 0.0f) { + prevVelocityY *= 0.5f; + mSpeed *= 0.5f; + } + sinkRate = nw4r::math::FAbs(prevVelocityY); + mVelocity.y = prevVelocityY; + mAcceleration = dAcPy_c::getBombAcceleration_1(); + mMaxSpeed = dAcPy_c::getBombMaxSpeed_1(); + } else if (attr == POLY_ATTR_SAND_DEEP_INSTANT || attr == POLY_ATTR_SAND_DEEP_SLOW || + attr == POLY_ATTR_SAND_MED) { + sinkTarget = -10.0f; + sinkRate = 1.0f; + } + if (attr == POLY_ATTR_SAND_DEEP_SLOW || attr == POLY_ATTR_SAND_MED) { + dTgStream_c::getForce(mPosition, force, dTgStream_c::sSandStreamList); + } + } + cLib::addCalcPosXZ(&mStreamForce, force, 0.5f, 10.0f, 3.0f); + sLib::chase(&sinkValue, sinkTarget, sinkRate); + mYOffset = sinkValue; + if (sinkValue <= -60.0f) { + setFlag(dAcBomb_c::FLAG_DELETE_BOMB); + } + setRoomId(); + + if (mAcch.ChkGndHit()) { + cM3dGPla plane; + dBgS::GetInstance()->GetTriPla(mAcch.GetGnd(), &plane); + mGndAngle = cM::atan2s(plane.GetN().absXZ(), plane.GetN().y); + + a1 = plane.GetN().atan2sX_Z(); + a0 = a1 - bombAngleY; + } + bool hit = false; + f32 outXZ = bombVelocity.absXZ(); + if (mAcch.ChkWallHit(nullptr) && mAng::abs(mAcchCir.GetWallAngleY() - bombAngleY) > 0x4400 && outXZ > 1.0f) { + bounceWall(mAcchCir.GetWallAngleY()); + hit = true; + startSoundWithFloatParam(SE_BM_BOUND, outXZ); + } else if (mAcch.ChkRoofHit() && mVelocity.y > 0.0f) { + startSoundWithFloatParam(SE_BM_BOUND, mVelocity.y); + mVelocity.y = 0.0f; + } else if (mAcch.ChkGroundLanding() && mSpeed > 5.0f && mGndAngle >= mAng::fromDeg(50.0f) && + mAng::abs(a0) >= 0x4000) { + bounceWall(a1); + mVelocity.y = prevVelocityY; + mAcch.ClrGroundLanding(); + mAcch.i_ClrGroundHit(); + hit = true; + } else if (mSph.ChkCoHit() && field_0xA42 == 0 && mStts.GetCcMove().absXZ() >= 1.0f) { + bounceWall(mStts.GetCcMove().atan2sX_Z()); + field_0xA42 = 5; + hit = true; + } + + mAng hitGndAngle = gndAngle; + if (hit) { + getVelocity(bombVelocity); + s16 sVar15 = bombVelocity.atan2sX_Z(); + if (mAcch.ChkGndHit()) { + hitGndAngle = mAcch.GetGnd().GetAngle(sVar15); + } + } + + if (mAcch.ChkGroundLanding()) { + if (prevVelocityY < -5.0f) { + startSoundWithFloatParam(SE_BM_BOUND, prevVelocityY * -1.0f); + if (dBgS::GetInstance()->GetPolyAtt0(mAcch.GetGnd()) != POLY_ATT_0_LAVA) { + dJEffManager_c::spawnGroundEffect(mPosition, mPolyAttr0, mPolyAttr1, field_0x1B4, 1, 0.8f, field_0x1B0); + } + } + + prevVelocityY *= -dAcPy_c::getBombBounceSpeed(); + s32 attr = dBgS::GetInstance()->GetSpecialCode(mAcch.mGnd); + + if (!checkFlag(dAcBomb_c::FLAG_ROLL) && + (prevVelocityY < dAcPy_c::getBombStopSpeedY() || + (attr == POLY_ATTR_SAND_DEEP_INSTANT || + (attr == POLY_ATTR_CURSED_WATER || attr == POLY_ATTR_SAND_DEEP_SLOW || attr == POLY_ATTR_SAND_MED)))) { + sLib::chase(&mSpeed, 0.0f, 7.0f); + } else { + mSpeed *= 0.9f; + mRollSpeed *= 0.9f; + + if (hitGndAngle < 0) { + mSpeed *= hitGndAngle.cos(); + mRollSpeed *= hitGndAngle.cos(); + } + + if (checkFlag(dAcBomb_c::FLAG_0x80000)) { + unsetFlag(dAcBomb_c::FLAG_0x80000); + mVelocity.y = 0.0f; + } else if (prevVelocityY > dAcPy_c::getBombMaxSpeedY()) { + mVelocity.y = dAcPy_c::getBombMaxSpeedY(); + } else { + mVelocity.y = prevVelocityY; + } + } + } else if (mAcch.ChkGndHit()) { + cM3dGPla plane; + dBgS::GetInstance()->GetTriPla(mAcch.mGnd, &plane); + int code = dBgS::GetInstance()->GetSpecialCode(mAcch.mGnd); + + f32 step; + if (checkFlag(dAcBomb_c::FLAG_ROLL)) { + if (code == POLY_ATTR_SAND_DEEP_SLOW || code == POLY_ATTR_SAND_MED) { + step = 0.2f; + } else { + step = 0.1f; + } + } else { + step = 0.75f; + } + if (code != POLY_ATTR_CURSED_WATER) { + if (mGndAngle >= mAng::fromDeg(20.0f)) { + mVec3_c v1 = 2.0f * plane.GetN() * mAng(mGndAngle.mVal).sin(); + v1.y = 0.0f; + + mAng yRot = v1.atan2sX_Z(); + f32 compare = mHitForce.squareMagXZ(); + if (compare > 1.0f) { + s32 a = yRot - mAng::fromVec(mHitForce); + if (mAng::abs(a) >= 0x4000) { + mHitForce.rotY(-yRot); + mHitForce.z *= 0.99f; + sLib::chase(&mHitForce.z, 0.0f, 1.0f); + mHitForce.rotY(yRot); + } + } + + if (mAng::abs(yRot - mAngle.y) >= 0x4000) { + sLib::chase(&mSpeed, 0.0f, step); + } + mSpeed *= 0.99f; + rollTo(v1); + mSpeed = nw4r::ut::Min(mSpeed, 30.0f); + + if (mAng::abs(yRot - mRollRotationY) >= 0x4000) { + sLib::chase(&mRollSpeed, 0.0f, step); + } + mRollSpeed *= 0.99f; + rollToInternal(v1); + mRollSpeed = nw4r::ut::Min(mRollSpeed, 30.0f); + } else { + sLib::chase(&mRollSpeed, 0.0f, step); + if (sLib::chase(&mSpeed, 0.0f, step)) { + if (mHitForce.getSquareMag() < 1.0f && mStreamForce.getSquareMag() < 1.0f) { + setPickupTarget(); + } + unsetFlag(dAcBomb_c::FLAG_ROLL); + mSph.ClrAtSet(); + } + } + } + } + + lookAt(); +} +void dAcBomb_c::finalizeState_Wait() { + mSph.SetCoCallback(dAcBomb_coHitCallback); + mSph.OnCoSet(); +} + +void dAcBomb_c::initializeState_FlowerWait() { + setFlag(dAcBomb_c::FLAG_FLOWER); + mSph.ClrTgSet(); + mScale.set(0.1f, 0.1f, 0.1f); + mStts.SetRank(0xD); + mAcch.OffLineCheck(); + mMdl.setScale(mScale); +} +void dAcBomb_c::executeState_FlowerWait() { + dAcPy_c *pPlayer = dAcPy_c::GetLink2(); + + if (mScale.x < 1.0f || field_0xA50 < 1.0f) { + if (mScale.x < 0.15f && !MinigameManager::GetInstance()->checkInThrillDigger() && + ((getBombType() == BOMBF_CRAWLSPACE && pPlayer->checkActionFlagsCont(dAcPy_c::ActFLG1_INCRAWLSPACE)) || + (getBombType() != BOMBF_CRAWLSPACE && !pPlayer->checkActionFlagsCont(dAcPy_c::ActFLG1_INCRAWLSPACE)))) { + startSound(SE_O_BOMB_FLOWER_SPROUT); + } + sLib::chase(&mScale.x, 1.0f, 0.1f); + mScale.z = mScale.y = mScale.x; + mVec3_c scale = mScale * field_0xA50; + mMdl.setScale(scale); + + mMtx_c m = mMtx; + m.setTranslation(mExternalTranslation); + setTransformFromFlower(m); + mSph.ClrTgSet(); + return; + } + + AttentionManager::GetInstance()->addUnk3Target(*this, 1, 250.0f, -200.0f, 200.0f); + lookAt(); + mSph.OnTgSet(); + mVec3_c scale = mScale * field_0xA50; + mMdl.setScale(scale); + + if (checkExplode()) { + return; + } + + if (mLinkage.checkState(dLinkage_c::STATE_ACTIVE)) { + changeState(StateID_Carry); + return; + } + + setPickupTarget(); +} +void dAcBomb_c::finalizeState_FlowerWait() { + if (!(mLinkage.checkConnection(dLinkage_c::CONNECTION_5) && checkFlag(dAcBomb_c::FLAG_FLOWER))) { + unsetFlag(dAcBomb_c::FLAG_FLOWER); + } + + if (getBombType() == BOMBF_CRAWLSPACE) { + mStts.SetRank(4); + } else { + mStts.SetRank(5); + } + + unsetActorProperty(AC_PROP_0x1); + mAcch.OnLineCheck(); +} + +void dAcBomb_c::initializeState_WindCarry() { + unsetFlag(dAcBomb_c::FLAG_BEETLE_CARRY | dAcBomb_c::FLAG_0x80000 | dAcBomb_c::FLAG_ROLL | dAcBomb_c::FLAG_0x10000); + mHitForce = mVec3_c::Zero; + mSpeed = 0.0f; + mVelocity = mVec3_c::Zero; + mRollSpeed = 0.0f; + mLinkage.bushTpFunc(mAcch); + setRoomId(); +} +void dAcBomb_c::executeState_WindCarry() { + if (checkExplode()) { + return; + } + + if (mLinkage.checkState(dLinkage_c::STATE_ACTIVE)) { + changeState(StateID_Carry); + return; + } + + if (mSph.ChkCoHit()) { + mPosition += mStts.GetCcMove(); + mUnkRef.fn_800051630(); + } + + if (!mUnkRef.fn_80051780(mSph)) { + changeState(StateID_Wait); + return; + } + + mLinkage.bushTpFunc(mAcch); + setRoomId(); + mSpeed = 0.0f; + mVelocity = mVec3_c::Zero; +} +void dAcBomb_c::finalizeState_WindCarry() {} + +void dAcBomb_c::setBombColor() { + mColor clr(0, 0, 0, 0xFF); + if (!checkFlag(dAcBomb_c::FLAG_FALL_IN_WATER)) { + bool b = !checkFlag( + dAcBomb_c::FLAG_FLOWER | dAcBomb_c::FLAG_0x200000 | dAcBomb_c::FLAG_FALL_IN_WATER | + dAcBomb_c::FLAG_NEAR_TIMEDOOR + ) && + !isState(StateID_Explode); + if (b) { + mEffect1.holdEffect(PARTICLE_RESOURCE_ID_MAPPING_974_, mWorldMtx, nullptr, nullptr); + if (!checkFlag(dAcBomb_c::FLAG_BOKO_CARRY)) { + mEffect2.holdEffect(PARTICLE_RESOURCE_ID_MAPPING_975_, mWorldMtx, nullptr, nullptr); + } + + dAcObjBase_c *pObj; + if ( + // Is controlled - and by player + // And Controlling Actor (player) as objprop 0x200 set + (mLinkage.checkState(dLinkage_c::STATE_ACTIVE) && static_cast<dAcObjBase_c *>(mLinkage.getControllingActor())->isPlayer()) + && ((pObj = static_cast<dAcObjBase_c *>(mLinkage.getControllingActor())) && pObj->checkObjectProperty(OBJ_PROP_0x200)) + // OOOOR this bomb has it set. + || checkObjectProperty(OBJ_PROP_0x200) + ) { + mEffect1.stopDrawParticles(); + mEffect2.stopDrawParticles(); + } else { + holdSound(SE_BM_IGNITION_LV); + mEffect1.playDrawParticles(); + mEffect2.playDrawParticles(); + } + + s32 interval; + s16 maxTime = dAcPy_c::getBombExplodeTimer(); + if (mFuseTime > maxTime) { + interval = maxTime >> 1; + } else if (mFuseTime > (maxTime >> 1)) { + interval = maxTime >> 2; + } else if (mFuseTime > (maxTime >> 2)) { + interval = maxTime >> 3; + } else { + interval = maxTime >> 4; + } + + s32 tmp1 = (mFuseTime / interval); + tmp1 = nw4r::ut::Max<s32>(mFuseTime - (tmp1 * interval) - 5, 0); + u8 colorVal = (1.0f / (interval - 5)) * tmp1 * 255.0f; + + clr.r = colorVal; + clr.b = colorVal; + } + } + + mMdl.setTevKColor(mMainMatID, GX_KCOLOR3, clr, false); +} + +void dAcBomb_c::rollTo(const mVec3_c &dir) { + mVec3_c v; + setXYZCirclePoint(v, mAngle.y, mSpeed, mVelocity.y); + v += dir; + + mAngle.y = v.atan2sX_Z(); + mSpeed = v.absXZ(); + mVelocity.y = v.y; +} + +void dAcBomb_c::rollToInternal(const mVec3_c &dir) { + if (mRollFrameTimer == 0) { + return; + } + mVec3_c v; + setXYZCirclePoint(v, mRollRotationY, mRollSpeed, 0.0f); + v += dir; + + v.y = 0.0f; + + mRollRotationY = v.atan2sX_Z(); + mRollSpeed = v.absXZ(); +} + +void dAcBomb_c::registerInEvent() { + if (!isState(StateID_Wait)) { + return; + } + + if (!mAcch.ChkGndHit()) { + return; + } + + const dAcObjBase_c *pObj = dBgS::GetInstance()->GetActorPointer(mAcch.GetGnd()); + if (pObj != nullptr && pObj->mProfileName != fProfile::OBJ_CANNON) { + if (pObj->checkActorProperty(AC_PROP_0x4) || EventManager::FUN_800a0570(pObj)) { + setActorProperty(AC_PROP_0x4); + } + } +} + +void dAcBomb_c::unkVirtFunc_0x6C() { + if (isState(StateID_Wait)) { + unsetActorProperty(AC_PROP_0x4); + } +} + +// NONMATCHING (https://decomp.me/scratch/4ws7h ) +int dAcBomb_c::actorExecute() { + unsetFlag(dAcBomb_c::FLAG_0x400000 | dAcBomb_c::FLAG_0x100); + mVec3_c v; + getVelocity(v); + + f32 f = mHitForce.getSquareMag(); + if (!checkFlag(dAcBomb_c::FLAG_0x8000)) { + if (f > 1.0f) { + v += mHitForce; + rollTo(mHitForce); + rollToInternal(mHitForce); + } + f = 0.0f; + mHitForce = mVec3_c::Zero; + } else { + unsetFlag(dAcBomb_c::FLAG_0x8000); + } + + mGndAngle = 0; + mSmokePosPrev = mSmokePosNext; + + executeState(); + + if (checkFlag(dAcBomb_c::FLAG_DELETE_BOMB)) { + deleteRequest(); + return SUCCEEDED; + } + + if (!isState(StateID_Explode)) { + if (checkFlag(dAcBomb_c::FLAG_FALL_IN_WATER)) { + if (sLib::chase(&mScale.x, 0.0f, 0.0875f)) { + deleteRequest(); + return SUCCEEDED; + } + + mScale.y = mScale.z = mScale.x; + mMdl.setScale(mScale); + } else if (mFuseTime < 4) { + f32 scale = nw4r::ut::Min((4 - mFuseTime) * (1.0f / 7.5f), 0.4f) + 1.0f; + mScale.set(scale, scale, scale); + mMdl.setScale(mScale); + } + + if (checkWaterIn()) { + if (!checkFlag(dAcBomb_c::FLAG_FALL_IN_WATER | dAcBomb_c::FLAG_UNDERWATER)) { + if (!checkFlag(dAcBomb_c::FLAG_0x20000000)) { + // !!! FPR alloc here is weird I guess + f32 diff0 = (mOldPosition.y - mPosition.y); + f32 diff1 = (mAcch.GetWtrGroundH() - mPosition.y); + + diff0 = nw4r::math::FAbs(diff0); + diff1 = nw4r::math::FAbs(diff1); + + mVec3_c pos; + if (diff0 < 1.0f) { + pos.x = mPosition.x; + pos.y = mAcch.GetWtrGroundH(); + pos.z = mPosition.z; + } else { + f32 f = diff1 / diff0; + if (f > 1.0f) { + f = 1.0f; + } + pos = f * mOldPosition + (1.0f - f) * mPosition; + } + dAcPy_c::fn_801E2FC0(pos, mAcch.mWtr, 0.8f); + } + startSound(SE_BM_FALL_WATER); + if (mLinkage.checkState(dLinkage_c::STATE_ACTIVE)) { + mLinkage.forceRemove(this); + } + setFlag(dAcBomb_c::FLAG_FALL_IN_WATER); + + mSmokePos = mVec3_c::Zero; + mSpeed *= 0.5f; + mVelocity.y *= 0.5f; + + mAcceleration = dAcPy_c::getBombAcceleration_1(); + mMaxSpeed = dAcPy_c::getBombMaxSpeed_1(); + } + + if (checkFlag(dAcBomb_c::FLAG_DELETE_BOMB)) { + deleteRequest(); + mSmokePos = mVec3_c::Zero; + return SUCCEEDED; + } + } else { + unsetFlag(dAcBomb_c::FLAG_UNDERWATER); + mAcceleration = dAcPy_c::getBombAcceleration(); + mMaxSpeed = dAcPy_c::getBombMaxSpeed(); + } + + if (mSpeed > 1.0f || f > 1.0f) { + mVec3_c v; + setXYZCirclePoint(v, mAngle.y, mSpeed, 0.0f); + bool gndNotHit = true; + if (f > 1.0f) { + v += mHitForce; + } else if (mAcch.ChkGndHit()) { + gndNotHit = false; + } + + mMtx_c m; + f32 f = v.absXZ(); + s32 atan0 = v.atan2sX_Z(); + mAng a1 = f / ((sHIO.getBombScale() * 2.0f * mScale.x) * M_PI) * 65536.0f; + mAng a0 = mAng(atan0) - mRotation.y; + m.YrotS(a0); + if (gndNotHit) { + a1.mVal >>= 1; + } + m.XrotM(a1); + m.YrotM(-a0); + MTXConcat(m, mMtx, mMtx); + } + + f32 scale = mScale.y * 25.0f; + f32 f = 0.0f; + if (mGndAngle != 0 && mGndAngle < 0x4000) { + /// TODO: Fake? mGndAngle load again + f32 f_temp = ((1.0f / mAng(mGndAngle.mVal).cos()) - 1.0f); + f = scale * nw4r::ut::Min(f_temp * 0.75f, 0.5f); + } + mLinkage.fn_800511E0(this); + mUnkRef.modifyMtx(); + + mMtx_c m2, m0, m1; + m0.transS(0.0f, scale, 0.0f); + mWorldMtx.concat(m0); + mWorldMtx.concat(mMtx); + + m1.transS(0.0f, -scale, 0.0f); + mWorldMtx.concat(m1); + + m2.transS(0.0f, f, 0.0f); + MTXConcat(m2, mWorldMtx, mWorldMtx); + + mMdl.setLocalMtx(mWorldMtx); + mVec3_c in(0.0f, mScale.y * sHIO.getBombScale(), 0.0f); + mWorldMtx.multVec(in, mPositionCopy2); + mPositionCopy3 = mPositionCopy2; + mSph.moveCenter(mPositionCopy2); + mSph.SetR(mScale.x * sHIO.getBombScale() * field_0xA50); + if (checkFlag(dAcBomb_c::FLAG_FALL_IN_WATER)) { + mSph.ClrTgSet(); + mSph.ClrTgHit(); + } + if (mSph.GetR() > 0.01f) { + dCcS::GetInstance()->Set(&mSph); + } else { + mSph.ClrCoHit(); + mSph.ClrTgHit(); + } + + if (!checkFlag(dAcBomb_c::FLAG_FALL_IN_WATER)) { + setSmokePos(); + } + + mMdl.calc(false); + setBombColor(); + } + + return SUCCEEDED; +} + +int dAcBomb_c::draw() { + if (isState(StateID_Explode) || + (getBombType() == BOMBF_CRAWLSPACE && !dAcPy_c::GetLink()->checkActionFlagsCont(0x400000))) { + return SUCCEEDED; + } + + drawModelType1(&mMdl); + + mQuat_c rot(0.0f, mScale.x * sHIO.getBombScale(), 0.0f, mScale.x * sHIO.getBombScale()); + + if (!isState(StateID_FlowerWait)) { + drawShadow(mShdw, nullptr, mWorldMtx, &rot, -1, -1, -1, -1, -1, mPosition.y - mAcch.GetGroundH()); + } return SUCCEEDED; } diff --git a/src/d/a/obj/d_a_obj_boomerang.cpp b/src/d/a/obj/d_a_obj_boomerang.cpp index fa901893..e1bb4ab2 100644 --- a/src/d/a/obj/d_a_obj_boomerang.cpp +++ b/src/d/a/obj/d_a_obj_boomerang.cpp @@ -184,7 +184,7 @@ int dAcBoomerang_c::create() { mAcch.Set(this, 1, &mAcchCir); mAcch.SetGroundUpY(20.f); - mAcch.SetField_0xD4(30.f); + mAcch.SetRoofCrrHeight(30.f); mAcch.ClrRoofNone(); mAcch.SetBeetle(); mAcch.OnWaterGrp(); diff --git a/src/d/col/bg/d_bg_s_acch.cpp b/src/d/col/bg/d_bg_s_acch.cpp index 63242f60..0746b8ae 100644 --- a/src/d/col/bg/d_bg_s_acch.cpp +++ b/src/d/col/bg/d_bg_s_acch.cpp @@ -53,19 +53,19 @@ dBgS_Acch::dBgS_Acch() field_0x0A8(0.0f), field_0x0AC(0.0f), mGroundHeight(-1e9f), - field_0x0B4(120.0f), + mGndChkOffset(120.0f), field_0x0C8(0.0f), field_0x0CC(0.0f), mRoofHeight(1e9f), - field_0x0D4(1.0f), + mRoofCrrHeight(1.0f), field_0x0D8(0.0f), mpOutPolyInfo(nullptr), mRoofH_0x0E0(0.0f), mGroundH_0x0E4(0.0f), field_0x0E8(1e9f), field_0x1D0(-1.0f), - field_0x2F4(1000.0f), - field_0x390(0), + mWtrCheckOffset(1000.0f), + mWtrMode(0), field_0x394(0) { SetPolyPassChk(GetPolyPassChkInfo()); SetGrpPassChk(GetGrpPassChkInfo()); @@ -159,7 +159,7 @@ void dBgS_Acch::GroundCheck(dBgS &bgs, bool param2) { mVec3_c gnd_pos = *GetPos(); // This Ordering is weird - f32 temp = (field_0x0B4 - field_0x0A8) + field_0x0AC; + f32 temp = (mGndChkOffset - field_0x0A8) + field_0x0AC; if (mFlags & ACCH_FLAG_0x20000) { if (temp <= 1.1f) { temp = 1.1f; @@ -199,7 +199,7 @@ void dBgS_Acch::GroundCheck(dBgS &bgs, bool param2) { } if (gnd_pos.y < mpPos->y + field_0x0E8 && - mpPos->y + field_0x0E8 < (field_0x0B4 - field_0x0A8) + field_0x0AC + mpPos->y) { + mpPos->y + field_0x0E8 < (mGndChkOffset - field_0x0A8) + field_0x0AC + mpPos->y) { gnd_pos.y = mpPos->y + field_0x0E8; } @@ -277,11 +277,11 @@ void dBgS_Acch::GroundRoofProc(dBgS &bgs, bool param2) { mRoofHeight = bgs.RoofChk(&mRoof); if (mRoofHeight != 1e9f) { - if (mpPos->y + field_0x0D4 > mRoofHeight) { - field_0x0D8 = mRoofHeight - field_0x0D4; + if (mpPos->y + mRoofCrrHeight > mRoofHeight) { + field_0x0D8 = mRoofHeight - mRoofCrrHeight; SetRoofHit(); - } else if (field_0x0C8 + field_0x0D4 > mRoofHeight) { - field_0x0D8 = mRoofHeight - field_0x0D4; + } else if (field_0x0C8 + mRoofCrrHeight > mRoofHeight) { + field_0x0D8 = mRoofHeight - mRoofCrrHeight; SetRoofHit(); } } @@ -414,8 +414,8 @@ void dBgS_Acch::SphCheck() { if (height > field_0x0A8 && field_0x0A8 > 0.0f) { height = field_0x0A8; } - if (height > field_0x0D4 && field_0x0D4 > 1.0f) { - height = field_0x0D4; + if (height > mRoofCrrHeight && mRoofCrrHeight > 1.0f) { + height = mRoofCrrHeight; } height *= 0.8f; } diff --git a/src/d/d_player_mdl.cpp b/src/d/d_player_mdl.cpp index 78e1e1bb..3e934cfd 100644 --- a/src/d/d_player_mdl.cpp +++ b/src/d/d_player_mdl.cpp @@ -999,8 +999,9 @@ void daPlayerModelBase_c::updateSwordModel() { } u32 daPlayerModelBase_c::getCurrentShieldPouchSlot() { - // Compiler quirk, inline function not inlined due to GetLink call - if (dScGame_c::currentSpawnInfo.getTrial() == SpawnInfo::TRIAL || dAcPy_c::GetLink()->isInBambooCuttingMinigame()) { + // Compiler quirk, inline function not inlined due to MinigameManager::GetInstance call + if (dScGame_c::currentSpawnInfo.getTrial() == SpawnInfo::TRIAL || + MinigameManager::GetInstance()->checkInBambooCutting()) { return POUCH_SLOT_NONE; } return FileManager::GetInstance()->getShieldPouchSlot(); diff --git a/src/d/lyt/d_lyt_do_button.cpp b/src/d/lyt/d_lyt_do_button.cpp index 4aaadfbd..7b58f0cd 100644 --- a/src/d/lyt/d_lyt_do_button.cpp +++ b/src/d/lyt/d_lyt_do_button.cpp @@ -9,6 +9,7 @@ #include "nw4r/math/math_types.h" #include "sized_string.h" #include "toBeSorted/event_manager.h" +#include "toBeSorted/minigame_mgr.h" struct dLytDoButton_HIO_c { dLytDoButton_HIO_c(); @@ -294,7 +295,7 @@ bool dLytDobutton_c::remove() { bool dLytDobutton_c::execute() { bool isInEvent = EventManager::isInEvent(); bool b1 = true; - if (dAcPy_c::GetLink()->isInBambooCuttingMinigame()) { + if (MinigameManager::GetInstance()->checkInBambooCutting()) { setActionTextStuff(ICON_12, ACT_DO_70, false); } if (field_0x490 == 0) { diff --git a/src/d/lyt/meter/d_lyt_meter_item_select.cpp b/src/d/lyt/meter/d_lyt_meter_item_select.cpp index 02bd0ca1..aaf4fe81 100644 --- a/src/d/lyt/meter/d_lyt_meter_item_select.cpp +++ b/src/d/lyt/meter/d_lyt_meter_item_select.cpp @@ -2714,23 +2714,16 @@ bool dLytMeterItemSelect_c::isWheelBlockedByCurrentAction() { if (dAcPy_c::LINK->getRidingActorType() == dAcPy_c::RIDING_LOFTWING || dAcPy_c::LINK->checkActionFlags(dAcPy_c::FLG0_SWING_ROPE) || dAcPy_c::LINK->checkCurrentAction(0x9C) || dAcPy_c::LINK->getRidingActorType() == dAcPy_c::RIDING_TRUCK_MINECART || - dAcPy_c::LINK->checkCurrentAction(0x95) || isInSpiralChargeTutorialMinigame() || isInRollercoasterMinigame() || - dAcPy_c::LINK->checkCurrentAction(0x8C) || dLytMeter_c::GetMain()->isInSwordDrawEvent() || - checkIsInSkykeepPuzzle() || dLytMeter_c::GetInstance()->getMeterField_0x13770() == 0) { + dAcPy_c::LINK->checkCurrentAction(0x95) || MinigameManager::GetInstance()->checkInSprialChargeTutorial() || + MinigameManager::GetInstance()->checkInRollerCoaster() || dAcPy_c::LINK->checkCurrentAction(0x8C) || + dLytMeter_c::GetMain()->isInSwordDrawEvent() || checkIsInSkykeepPuzzle() || + dLytMeter_c::GetInstance()->getMeterField_0x13770() == 0) { return true; } return false; } -bool dLytMeterItemSelect_c::isInSpiralChargeTutorialMinigame() { - return MinigameManager::isInMinigameState(MinigameManager::SPIRAL_CHARGE_TUTORIAL); -} - -bool dLytMeterItemSelect_c::isInRollercoasterMinigame() { - return MinigameManager::isInMinigameState(MinigameManager::ROLLERCOASTER); -} - void dLytMeterItemSelect_c::setCurrentItemText(ITEM_ID item) { if (item >= ITEM_NONE && field_0x5754 == 0) { mText[1].setShouldBeSelect(true); diff --git a/src/d/tg/d_t_alldie.cpp b/src/d/tg/d_t_alldie.cpp new file mode 100644 index 00000000..a205ce09 --- /dev/null +++ b/src/d/tg/d_t_alldie.cpp @@ -0,0 +1,112 @@ +#include "d/t/d_t_alldie.h" + +#include "common.h" +#include "d/a/d_a_player.h" +#include "d/a/e/d_a_en_base.h" +#include "d/a/obj/d_a_obj_base.h" +#include "d/d_stage.h" +#include "d/flag/sceneflag_manager.h" +#include "f/f_base.h" +#include "f/f_manager.h" +#include "f/f_profile_name.h" +#include "s/s_Math.h" +#include "toBeSorted/area_math.h" +#include "toBeSorted/event_manager.h" + +SPECIAL_ACTOR_PROFILE(ALLDIE_TAG, dTgAllDie_c, fProfile::ALLDIE_TAG, 0x23, 0, 4); + +int dTgAllDie_c::create() { + mSceneflag = getFromParams(4, 0xFF); + mType = getFromParams(12, 0x3); + mTimer0x140 = getFromParams(22, 0xFF); + field_0x148 = 0; + field_0x144 = getFromParams(30, 0xFF); + mRotation.x.set(0); + matrixCreateFromPosRotYScale(mArea, mPosition, mRotation.y, mScale, nullptr, 0.0f); + return SUCCEEDED; +} + +int dTgAllDie_c::doDelete() { + return SUCCEEDED; +} + +int dTgAllDie_c::actorExecute() { + if (!dStage_c::GetInstance()->isRoomID(mRoomID)) { + return SUCCEEDED; + } + + if (mType <= 1) { + if (dTimeAreaMgr_c::fn_800BBD40()) { + return SUCCEEDED; + } + + mTimeArea.check(mRoomID, mPosition, 0, 10.0f, 0.1f); + f32 f = mTimeArea.getDistMaybe(); + if (mType == 0 && f < 1.0f) { + return SUCCEEDED; + } + if (mType == 1 && 0.0f < f) { + return SUCCEEDED; + } + } + + mNumEnemiesInArea = 0; + dAcEnBase_c *pEnemy = nullptr; + while ((pEnemy = dAcEnBase_c::GetNextEnemy(pEnemy))) { + if (pEnemy->mRoomID == mRoomID && !pEnemy->checkInteractionFlags(0x2)) { + if (pEnemy->checkProcControl(DISABLE_EXECUTE) == 0 && pEnemy->mLifecycleState != TO_BE_DELETED) { + if (checkAreaBox(mArea, pEnemy->mPosition)) { + mNumEnemiesInArea++; + } + } + } + } + + if (mNumEnemiesInArea == 0) { + if (field_0x148 != 0 && EventManager::isInEvent()) { + return SUCCEEDED; + } + + if (sLib::calcTimer(&mTimer0x13C) == 0) { + if (mSceneflag < 0xFF && !SceneflagManager::sInstance->checkBoolFlag(mRoomID, mSceneflag)) { + SceneflagManager::sInstance->setFlag(mRoomID, mSceneflag); + } + } + } else { + mTimer0x13C = (mTimer0x140 <= 128 ? mTimer0x140 + 40 : 40 - (256 - mTimer0x140)); + if (mSceneflag < 0xFF && SceneflagManager::sInstance->checkBoolFlag(mRoomID, mSceneflag)) { + SceneflagManager::sInstance->unsetFlag(mRoomID, mSceneflag); + } + } + return SUCCEEDED; +} + +int dTgAllDie_c::draw() { + return SUCCEEDED; +} + +dTgAllDie_c *dTgAllDie_c::getNearestToPlayer(s32 roomId) { + fBase_c *pPrev = nullptr; + dTgAllDie_c *pReturn = nullptr; + const dAcPy_c *pPlayer = dAcPy_c::GetLink(); + f32 minDist = 1e10f; + + while (true) { + dTgAllDie_c *pTgAllDie = + static_cast<dTgAllDie_c *>(fManager_c::searchBaseByProfName(fProfile::ALLDIE_TAG, pPrev)); + pPrev = pTgAllDie; + + if (pTgAllDie == nullptr) { + break; + } + + if (roomId == pTgAllDie->mRoomID) { + f32 dist = pPlayer->getPosition().squareDistanceToXZ(pTgAllDie->getPosition()); + if (dist < minDist) { + pReturn = pTgAllDie; + minDist = dist; + } + } + } + return pReturn; +} diff --git a/src/d/tg/d_t_view_clip.cpp b/src/d/tg/d_t_view_clip.cpp new file mode 100644 index 00000000..30ef9cba --- /dev/null +++ b/src/d/tg/d_t_view_clip.cpp @@ -0,0 +1,93 @@ +#include "d/t/d_t_view_clip.h" + +#include "common.h" +#include "d/d_camera.h" +#include "d/d_sc_game.h" +#include "f/f_base.h" +#include "toBeSorted/area_math.h" +#include "toBeSorted/area_utils.h" + +SPECIAL_ACTOR_PROFILE(VIEW_CLIP_TAG, dTgViewClip_c, fProfile::VIEW_CLIP_TAG, 0xB, 0, 0); + +u8 dTgViewClip_c::sViewClips[dTgViewClip_c::sNumEntries] = {}; + +int dTgViewClip_c::create() { + mIndex = getFromParams(0, 0x3F); + mType = getFromParams(8, 0xF); + if (mType == 0xF) { + mType = TYPE_FORCE_OFF; + } + + mAreaIndex = getFromParams(12, 0xFF); + matrixCreateFromPosRotYScale(mArea, mPosition, mRotation.y, mScale, nullptr, 0.0f); + + return SUCCEEDED; +} + +int dTgViewClip_c::doDelete() { + return SUCCEEDED; +} + +int dTgViewClip_c::actorExecute() { + return SUCCEEDED; +} + +int dTgViewClip_c::draw() { + dCamera_c *pCamera = dScGame_c::getCamera(); + if (!checkAreaBox(mArea, pCamera->getPosition())) { + if (mAreaIndex == 0xFF) { + return SUCCEEDED; + } + if (!checkPosInArea(mAreaIndex, mRoomID, pCamera->getPosition(), nullptr)) { + return SUCCEEDED; + } + } + + switch (mType) { + case TYPE_FORCE_ON: setViewClip(FLAG_FORCE_ON); break; + case TYPE_FORCE_OFF: setViewClip(FLAG_FORCE_OFF); break; + } + + return SUCCEEDED; +} + +void dTgViewClip_c::setViewClip(u8 setBit) { + setViewClipBit(mIndex, setBit); +} + +void dTgViewClip_c::resetViewClip() { + for (int i = 0; i < sNumEntries - 1; ++i) { + setViewClip(i, 0); + } +} + +f32 dTgViewClip_c::getCull(s32 idx, f32 cullDistance) { + if (idx > ARRAY_LENGTH(sViewClips) - 2) { + return cullDistance; + } + + if (getViewClipBit(idx, FLAG_FORCE_ON)) { + return FLOAT_MAX; + } else if (getViewClipBit(idx, FLAG_FORCE_OFF)) { + return -1.0f; + } + + return cullDistance; +} +bool dTgViewClip_c::checkForceOn(s32 idx) { + if (idx <= ARRAY_LENGTH(sViewClips) - 2) { + return getViewClipBit(idx, FLAG_FORCE_ON); + } + return false; +} + +u8 dTgViewClip_c::getViewClipBit(s32 idx, u8 setBit) { + return sViewClips[idx] & setBit; +} +void dTgViewClip_c::setViewClipBit(s32 idx, u8 setBit) { + sViewClips[idx] |= setBit; +} + +void dTgViewClip_c::setViewClip(s32 idx, u8 value) { + sViewClips[idx] = value; +} |
