summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorelijah-thomas774 <elijahthomas774@gmail.com>2026-09-24 18:15:38 -0400
committerelijah-thomas774 <elijahthomas774@gmail.com>2026-09-24 18:15:38 -0400
commite9199fba27c8f193dc0c7d36daf73006d8dc5e19 (patch)
tree32bc11c6d45b2cc14b8a2139072f787b558d462e /src
parentfe566ba5dbc764a01774643f8a47b7ff5d53fd87 (diff)
parentdf3d2023e89b5b89f2ecb9f53faa9b0e61e2c958 (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.cpp38
-rw-r--r--src/REL/d/a/e/d_a_e_ks.cpp14
-rw-r--r--src/REL/d/a/e/d_a_e_remly.cpp4
-rw-r--r--src/REL/d/a/e/d_a_e_sm.cpp6
-rw-r--r--src/REL/d/a/obj/d_a_obj_barrel.cpp10
-rw-r--r--src/REL/d/a/obj/d_a_obj_tubo.cpp2
-rw-r--r--src/REL/d/t/d_t_action.cpp2
-rw-r--r--src/d/a/d_a_item.cpp2
-rw-r--r--src/d/a/d_a_player.cpp143
-rw-r--r--src/d/a/obj/d_a_obj_bomb.cpp1240
-rw-r--r--src/d/a/obj/d_a_obj_boomerang.cpp2
-rw-r--r--src/d/col/bg/d_bg_s_acch.cpp24
-rw-r--r--src/d/d_player_mdl.cpp5
-rw-r--r--src/d/lyt/d_lyt_do_button.cpp3
-rw-r--r--src/d/lyt/meter/d_lyt_meter_item_select.cpp15
-rw-r--r--src/d/tg/d_t_alldie.cpp112
-rw-r--r--src/d/tg/d_t_view_clip.cpp93
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;
+}