summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorElijah Thomas <42302100+elijah-thomas774@users.noreply.github.com>2025-05-25 15:51:35 -0400
committerGitHub <noreply@github.com>2025-05-25 15:51:35 -0400
commitfd7d30d32283d03a412e8c401d04418351cf686a (patch)
treee88bed25f474f06552cd7a7ea7067a0beead4414 /src
parent018ef1971cd53aa8e78154789bcf6cac2f19b603 (diff)
d_linkage is largely done (#176)
Diffstat (limited to 'src')
-rw-r--r--src/REL/d/a/e/d_a_e_sm.cpp3
-rw-r--r--src/REL/d/a/obj/d_a_obj_ring.cpp14
-rw-r--r--src/REL/d/a/obj/d_a_obj_tubo.cpp48
-rw-r--r--src/d/a/obj/d_a_obj_arrow.cpp5
-rw-r--r--src/d/a/obj/d_a_obj_boomerang.cpp95
-rw-r--r--src/d/a/obj/d_a_obj_switch.cpp34
-rw-r--r--src/d/d_carry.cpp12
-rw-r--r--src/d/d_linkage.cpp251
-rw-r--r--src/m/m_mtx.cpp48
9 files changed, 443 insertions, 67 deletions
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 fe3c7514..dae7f886 100644
--- a/src/REL/d/a/e/d_a_e_sm.cpp
+++ b/src/REL/d/a/e/d_a_e_sm.cpp
@@ -16,6 +16,7 @@
#include "d/col/cc/d_cc_s.h"
#include "d/d_camera.h"
#include "d/d_jnt_col.h"
+#include "d/d_linkage.h"
#include "d/d_sc_game.h"
#include "d/flag/sceneflag_manager.h"
#include "d/flag/storyflag_manager.h"
@@ -629,7 +630,7 @@ int dAcEsm_c::actorExecute() {
dAcBomb_c *bomb = getBombWithinRadius(lookRadius);
if (bomb != nullptr && std::abs(bomb->GetPosition().y - mHomePos1.y) < 0.7f * lookRadius) {
- if (bomb->mActorCarryInfo.tryAttachWithRef(bomb, this, &mBombRef, 1, false)) {
+ if (bomb->GetLinkage().tryAttach(bomb, this, &mBombRef, dLinkage_c::CONNECTION_1, false)) {
mTimer_0xBAE = 160;
playSound(SE_ESm_BRING_IN);
clearActorProperty(1);
diff --git a/src/REL/d/a/obj/d_a_obj_ring.cpp b/src/REL/d/a/obj/d_a_obj_ring.cpp
index 554a9d35..7d52f2bb 100644
--- a/src/REL/d/a/obj/d_a_obj_ring.cpp
+++ b/src/REL/d/a/obj/d_a_obj_ring.cpp
@@ -1,6 +1,8 @@
#include "d/a/obj/d_a_obj_ring.h"
#include "d/a/d_a_player.h"
+#include "d/d_linkage.h"
+#include "m/m_angle.h"
#include "nw4r/g3d/res/g3d_resfile.h"
SPECIAL_ACTOR_PROFILE(OBJ_RING, dAcOring_c, fProfile::OBJ_RING, 0x00f2, 0, 0x103);
@@ -10,7 +12,6 @@ STATE_DEFINE(dAcOring_c, Move);
bool dAcOring_c::createHeap() {
nw4r::g3d::ResFile f(getOarcResFile("PRing"));
nw4r::g3d::ResMdl mdl = f.GetResMdl("PeehatRing");
- // This matches but in a really weird way. Maybe an inline function?
TRY_CREATE(mModel.create(mdl, &heap_allocator, 0x20, 1, nullptr));
return true;
}
@@ -52,18 +53,11 @@ int dAcOring_c::draw() {
void dAcOring_c::initializeState_Move() {}
-u32 dAcOring_c::ROT_PER_TICK = 0x1000;
-
void dAcOring_c::executeState_Move() {
- bool isCarried = false;
- if (mActorCarryInfo.isCarried == 1 && mActorCarryInfo.carryType == 7) {
- isCarried = true;
- }
-
- if (isCarried) {
+ if (GetLinkage().checkConnection(dLinkage_c::CONNECTION_7)) {
return;
}
- rotation.x.mVal += ROT_PER_TICK;
+ rotation.addX(0x1000);
if (field_0x38C >= position.y) {
deleteRequest();
}
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 2c6d42ec..bfcb4ba7 100644
--- a/src/REL/d/a/obj/d_a_obj_tubo.cpp
+++ b/src/REL/d/a/obj/d_a_obj_tubo.cpp
@@ -17,6 +17,7 @@
#include "d/col/c/c_cc_d.h"
#include "d/col/c/c_m3d_g_pla.h"
#include "d/col/cc/d_cc_s.h"
+#include "d/d_linkage.h"
#include "d/flag/dungeonflag_manager.h"
#include "d/flag/sceneflag_manager.h"
#include "egg/math/eggMath.h"
@@ -104,11 +105,11 @@ int dAcOtubo_c::actorCreate() {
mStateMgr.changeState(StateID_Wait);
boundingBox.Set(mVec3_c(-100.f, -40.f, -100.f), mVec3_c(100.f, 80.f, 100.f));
- mActorCarryInfo.set(0xC8A0, 28.f, 50.f, 28.f, nullptr); // TODO (ActorCarry Flags)
- mActorCarryInfo.field_0x8C = 26.f;
- mActorCarryInfo.field_0x90 = 46.f;
- mActorCarryInfo.field_0x94 = 28.f;
- mActorCarryInfo.field_0x98 = 0.f;
+ GetLinkage().set(0xC8A0, 28.f, 50.f, 28.f, nullptr); // TODO (ActorCarry Flags)
+ GetLinkage().field_0x8C = 26.f;
+ GetLinkage().field_0x90 = 46.f;
+ GetLinkage().field_0x94 = 28.f;
+ GetLinkage().field_0x98 = 0.f;
return SUCCEEDED;
}
@@ -166,7 +167,7 @@ int dAcOtubo_c::actorExecute() {
mField_0x9DC += position.y - mOldPosition.y;
adjustRoll();
}
- mActorCarryInfo.bushTpFunc(mObjAcch);
+ GetLinkage().bushTpFunc(mObjAcch);
}
if (mStateMgr.isState(StateID_Wait) || mStateMgr.isState(StateID_Slope)) {
@@ -175,7 +176,7 @@ int dAcOtubo_c::actorExecute() {
mSph.SetC(getCenter());
dCcS::GetInstance()->Set(&mSph);
- mActorCarryInfo.fn_800511E0(this);
+ GetLinkage().fn_800511E0(this);
mField_0x8F0.modifyMtx();
calcRoll();
@@ -283,28 +284,23 @@ void dAcOtubo_c::executeState_Grab() {
dAcNpcCeLady_c *lady = mCeLady.get();
dAcNpcCeFriend_c *ceFriend = mCeFriend.get();
if (ceFriend && ceFriend->fn_11_17C0(this)) {
- mActorCarryInfo.fn_80050EA0(this);
+ GetLinkage().fn_80050EA0(this);
} else if (lady && lady->fn_12_1C20(this)) {
- mActorCarryInfo.fn_80050EA0(this);
+ GetLinkage().fn_80050EA0(this);
}
}
- if (mActorCarryInfo.checkCarryType(5) && sLib::calcTimer(&mTimer_0x9F5) == 0 &&
+ if (GetLinkage().checkConnection(dLinkage_c::CONNECTION_5) && sLib::calcTimer(&mTimer_0x9F5) == 0 &&
(mObjAcch.ChkGndHit() || mObjAcch.ChkWallHit(nullptr) || mObjAcch.ChkRoofHit())) {
destroy();
- } else if (dAcPy_c::LINK->getCurrentAction() == 66 /* Put Down Medium */) { // TODO (Link Action ID)
+ } else if (dAcPy_c::GetLink()->getCurrentAction() == 66 /* Put Down Medium */) { // TODO (Link Action ID)
mStateMgr.changeState(StateID_Put);
} else {
- if (mActorCarryInfo.isCarried != 4) {
- bool isCarried = false;
- if (mActorCarryInfo.isCarried == 1 && mActorCarryInfo.carryType == 5) {
- isCarried = true;
- }
-
- if (isCarried) {
- mField_0x9F6 = 0;
+ if (!GetLinkage().checkState(dLinkage_c::STATE_DELETE)) {
+ if (GetLinkage().checkConnection(dLinkage_c::CONNECTION_5)) {
+ mField_0x9F6 = dLinkage_c::STATE_0;
} else {
- mField_0x9F6 = mActorCarryInfo.isCarried;
+ mField_0x9F6 = GetLinkage().getState();
}
}
@@ -320,7 +316,7 @@ void dAcOtubo_c::finalizeState_Grab() {
}
mField_0x9D4 = cM::rndF(40.f);
mSph.ClrCo_0x400();
- if ((u8)mActorCarryInfo.isCarried == 2) {
+ if ((u8)GetLinkage().mState == 2) {
mSph.OnAtSet();
}
mObjAcch.ClrRoofNone();
@@ -407,7 +403,7 @@ void dAcOtubo_c::initializeState_Rebirth() {
mSph.ClrCoSet();
mSph.ClrTgSet();
setObjectProperty(0x200);
- mActorCarryInfo.fn_80050EA0(this);
+ GetLinkage().fn_80050EA0(this);
int item_drop_table = getParams2UpperByte();
switch (item_drop_table) {
@@ -456,7 +452,7 @@ void dAcOtubo_c::destroy() {
return;
}
fn_80022BE0(BlurAndPaletteManager::GetPInstance(), position);
- mActorCarryInfo.fn_80050EA0(this);
+ GetLinkage().fn_80050EA0(this);
dEmitterBase_c *fx_thing = dJEffManager_c::spawnEffect(
PARTICLE_RESOURCE_ID_MAPPING_211_, poscopy2, nullptr, nullptr, nullptr, nullptr, 0, 0
@@ -651,7 +647,7 @@ void dAcOtubo_c::attemptDestroy() {
mField_0x9DC = 0.f;
}
if (!mObjAcch.ChkGndHit() && mSph.ChkCoHit()) {
- if (mActorCarryInfo.isCarried != 1 && forwardSpeed > 0.f) {
+ if (GetLinkage().mState != 1 && forwardSpeed > 0.f) {
if (mSph.GetCoActor()->unkByteTargetFiRelated == 4) {
destroy();
return;
@@ -807,7 +803,9 @@ bool dAcOtubo_c::checkOnLava() {
}
bool dAcOtubo_c::checkCarryType() const {
- return mActorCarryInfo.checkCarryType(1) || mActorCarryInfo.checkCarryType(7) || mActorCarryInfo.checkCarryType(5);
+ const dLinkage_c &linkage = GetLinkage();
+ return linkage.checkConnection(dLinkage_c::CONNECTION_1) || linkage.checkConnection(dLinkage_c::CONNECTION_7) ||
+ linkage.checkConnection(dLinkage_c::CONNECTION_5);
}
bool dAcOtubo_c::checkSubmerged() {
diff --git a/src/d/a/obj/d_a_obj_arrow.cpp b/src/d/a/obj/d_a_obj_arrow.cpp
index 42e1965d..2b9bbb57 100644
--- a/src/d/a/obj/d_a_obj_arrow.cpp
+++ b/src/d/a/obj/d_a_obj_arrow.cpp
@@ -1,7 +1,6 @@
#include "d/a/obj/d_a_obj_arrow.h"
#include "c/c_math.h"
-#include "d/a/d_a_player.h"
#include "d/col/c/c_cc_d.h"
#include "nw4r/types_nw4r.h"
@@ -38,7 +37,7 @@ const dCcD_SrcSph dAcArrow_c::sCc2 = {
// clang-format on
-bool hitCallback(dAcObjBase_c *i_actorA, cCcD_Obj *i_objInfA, dAcObjBase_c *i_actorB, cCcD_Obj *i_objInfB) {
+bool dAcArrow_atHitCallback(dAcObjBase_c *i_actorA, cCcD_Obj *i_objInfA, dAcObjBase_c *i_actorB, cCcD_Obj *i_objInfB) {
static_cast<dAcArrow_c *>(i_actorA)->hitCallback(i_objInfA, i_actorB, i_objInfB);
return true;
}
@@ -70,7 +69,7 @@ int dAcArrow_c::create() {
mCcCps.Set(sCc1);
mCcCps.SetStts(mStts);
mCcCps.SetAtFlag(0x2000);
- mCcCps.SetAtCallback(::hitCallback);
+ mCcCps.SetAtCallback(dAcArrow_atHitCallback);
mCcSph.Set(sCc2);
mCcSph.SetStts(mStts);
diff --git a/src/d/a/obj/d_a_obj_boomerang.cpp b/src/d/a/obj/d_a_obj_boomerang.cpp
new file mode 100644
index 00000000..1f908925
--- /dev/null
+++ b/src/d/a/obj/d_a_obj_boomerang.cpp
@@ -0,0 +1,95 @@
+#include "d/a/obj/d_a_obj_boomerang.h"
+
+#include "common.h"
+#include "d/a/d_a_player.h"
+#include "d/a/obj/d_a_obj_base.h"
+#include "f/f_profile_name.h"
+#include "m/m3d/m_fanm.h"
+#include "nw4r/g3d/g3d_anmchr.h"
+#include "nw4r/g3d/res/g3d_resmdl.h"
+#include "s/s_State.hpp"
+
+SPECIAL_ACTOR_PROFILE(BOOMERANG, dAcBoomerang_c, fProfile::BOOMERANG, 0x125, 0, 0x4);
+
+STATE_DEFINE(dAcBoomerang_c, Wait);
+STATE_DEFINE(dAcBoomerang_c, Move);
+STATE_DEFINE(dAcBoomerang_c, MoveCancelWait);
+STATE_DEFINE(dAcBoomerang_c, ReturnWait);
+STATE_DEFINE(dAcBoomerang_c, EventReturnWait);
+
+const dAcBoomerang_c::ChrAnimation_t dAcBoomerang_c::sChrAnims[dAcBoomerang_c::RB_MAX] = {
+ { "RB_Set", 0.f},
+ {"RB_Default", 3.f},
+ { "RB_Cut", 3.f},
+ { "RB_Hold", 3.f},
+ {"RB_Hold_ed", 3.f},
+ { "RB_Back", 3.f},
+};
+
+void areaCallback(dAcObjBase_c *param0, mVec3_c *param1, u32 param2) {
+ if (param2 != 0) {
+ return;
+ }
+}
+
+void dAcBoomerang_c::atHitCallback(cCcD_Obj *i_objInfA, dAcObjBase_c *i_actorB, cCcD_Obj *i_objInfB) {
+ if (i_actorB != nullptr && GetLinkage().checkFlag(0x80)) {
+ if (dAcPy_c::getCurrentBeetleType() > 2) {
+ if (i_actorB == mGrabbedActor.get()) {
+ return;
+ }
+
+ if (!mStateMgr.isState(StateID_Move)) {
+ return;
+ }
+
+ if (tryGrabObject(i_actorB)) {
+ setChrAnimation(RB_HOLD);
+ mAnmChr[0].setRate(0.f);
+ mAnmChr[0].setFrameOnly(i_actorB->GetLinkage().field_0x24);
+ }
+ }
+ }
+}
+
+bool dAcBoomerang_atHitCallback(
+ dAcObjBase_c *i_actorA, cCcD_Obj *i_objInfA, dAcObjBase_c *i_actorB, cCcD_Obj *i_objInfB
+) {
+ static_cast<dAcBoomerang_c *>(i_actorA)->atHitCallback(i_objInfA, i_actorB, i_objInfB);
+ return true;
+}
+
+// ...
+
+bool dAcBoomerang_c::tryGrabObject(dAcObjBase_c *pObj) {
+ dAcPy_c *player = dAcPy_c::GetLink2();
+ if (checkField_0x8CC(0x1000) && GetLinkage().checkFlag(0x80)) {}
+}
+
+// ...
+
+void dAcBoomerang_c::setChrAnimation(dAcBoomerang_c::ChrAnimation_e requestedAnimation) {
+ // Do not set anim if there is no change, or the request is to cut from hold
+ if (requestedAnimation == mCurrentAnimation || (mCurrentAnimation == RB_HOLD && requestedAnimation == RB_CUT)) {
+ return;
+ }
+
+ mAnmChr[0].setAnm(mMdl, mResFile.GetResAnmChr(sChrAnims[requestedAnimation].mName), m3d::PLAY_MODE_4);
+ nw4r::g3d::AnmObjChr *pAnmObj = static_cast<nw4r::g3d::AnmObjChr *>(mAnmChr[0].getAnimObj());
+
+ pAnmObj->Release();
+
+ nw4r::g3d::ResMdl mdl = mMdl.getResMdl();
+ for (int i = 0; i < mWindNodeID; ++i) {
+ pAnmObj->Bind(mdl, i, nw4r::g3d::AnmObjChr::BIND_ONE);
+ }
+
+ if (requestedAnimation == RB_SET) {
+ pAnmObj->Bind(mdl, mLeftWingNodeID, nw4r::g3d::AnmObjChr::BIND_ONE);
+ pAnmObj->Bind(mdl, mRightWingNodeID, nw4r::g3d::AnmObjChr::BIND_ONE);
+ }
+
+ mCurrentAnimation = requestedAnimation;
+
+ mMdl.setAnm(mAnmChrBlend, sChrAnims[requestedAnimation].mRate);
+}
diff --git a/src/d/a/obj/d_a_obj_switch.cpp b/src/d/a/obj/d_a_obj_switch.cpp
index ffc58d74..fd5cd444 100644
--- a/src/d/a/obj/d_a_obj_switch.cpp
+++ b/src/d/a/obj/d_a_obj_switch.cpp
@@ -3,6 +3,7 @@
#include "d/a/d_a_player.h"
#include "d/col/bg/d_bg_s.h"
#include "d/col/bg/d_bg_w.h"
+#include "d/d_linkage.h"
#include "d/flag/sceneflag_manager.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "s/s_Math.h"
@@ -42,26 +43,29 @@ void dAcOsw_c::rideCallback(dBgW *unknown, dAcObjBase_c *actor, dAcObjBase_c *in
dAcPy_c *link = interactor->isActorPlayer() ? static_cast<dAcPy_c *>(interactor) : nullptr;
dAcOsw_c *sw = static_cast<dAcOsw_c *>(actor);
- // halp
- if (!(link == nullptr || (!link->checkActionFlags(dAcPy_c::FLG0_IN_WATER) &&
- ((!link->checkFlags0x340(0x800000) ||
- ((link->getCurrentCarriedActor() != nullptr &&
- link->getCurrentCarriedActor()->mActorCarryInfo.testCarryFlag(0x04)))))))) {
+ if (link != nullptr) {
+ if (link->checkActionFlags(dAcPy_c::FLG0_IN_WATER)) {
+ return;
+ }
+ if (link->checkFlags0x340(0x800000) &&
+ !(link->getCurrentCarriedActor() && link->getCurrentCarriedActor()->GetLinkage().checkFlag(0x04))) {
+ return;
+ }
+ }
+
+ if (interactor->GetLinkage().checkState(dLinkage_c::STATE_ACTIVE)) {
return;
}
- if (interactor->mActorCarryInfo.isCarried != 1) {
- if (link == nullptr || (link->checkActionFlags(0xC70852)) == 0) {
- if (!sw->someInteractCheck(link != nullptr)) {
- bool needsOnFlag = sw->mOnSceneFlag < 0xFF &&
- !SceneflagManager::sInstance->checkBoolFlag(sw->roomid, sw->mOnSceneFlag);
- if (!needsOnFlag && sw->mObjRef.get() == nullptr && link != nullptr && sw->field_0x5F1 == 0 &&
- sw->mStateMgr.isState(StateID_On)) {
- link->onFlags_0x360(0x8000);
- }
+
+ if (!(link && link->checkActionFlags(0xC70852))) {
+ if (!sw->someInteractCheck(link != nullptr)) {
+ if (!sw->checkOnFlag() && sw->mObjRef.get() == nullptr && link != nullptr && sw->field_0x5F1 == 0 &&
+ sw->mStateMgr.isState(StateID_On)) {
+ link->onFlags_0x360(0x8000);
}
}
- interactor->setObjectProperty(0x40);
}
+ interactor->setObjectProperty(0x40);
}
bool dAcOsw_c::createHeap() {
diff --git a/src/d/d_carry.cpp b/src/d/d_carry.cpp
deleted file mode 100644
index ce473dd4..00000000
--- a/src/d/d_carry.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "d/a/obj/d_a_obj_base.h"
-#include "m/m_mtx.h"
-
-ActorCarryStruct::ActorCarryStruct()
- : actorLink(nullptr), carriedActor(nullptr), carryFlags(0), carryType(0), field_0x18(0),
- field_0x1C(0.0f, 0.0f, 0.0f), carryTransMtx(mMtx_c::Identity), field_0x58(mMtx_c::Identity), isCarried(0),
- field_0x8C(0.0f), field_0x90(0.0f), field_0x94(0.0f), field_0x98(0.0f) {}
-
-ActorCarryStruct::~ActorCarryStruct() {
- fn_80051190(nullptr);
- fn_80050EB0(nullptr);
-}
diff --git a/src/d/d_linkage.cpp b/src/d/d_linkage.cpp
new file mode 100644
index 00000000..c37f6118
--- /dev/null
+++ b/src/d/d_linkage.cpp
@@ -0,0 +1,251 @@
+#include "d/d_linkage.h"
+
+#include "common.h"
+#include "d/a/d_a_player.h"
+#include "d/a/obj/d_a_obj_base.h"
+#include "d/col/bg/d_bg_s.h"
+#include "d/col/bg/d_bg_s_acch.h"
+#include "f/f_profile_name.h"
+#include "m/m_mtx.h"
+#include "m/m_vec.h"
+#include "rvl/MTX/mtx.h"
+
+dLinkage_c::dLinkage_c()
+ : mControllingActor(nullptr),
+ pLinkedActor(nullptr),
+ carryFlags(0),
+ mType(CONNECTION_0),
+ field_0x18(0),
+ field_0x1C(0.0f),
+ field_0x20(0.f),
+ field_0x24(0.f),
+ carryTransMtx(mMtx_c::Identity),
+ field_0x58(mMtx_c::Identity),
+ mState(STATE_0),
+ field_0x8C(0.0f),
+ field_0x90(0.0f),
+ field_0x94(0.0f),
+ field_0x98(0.0f) {}
+
+dLinkage_c::~dLinkage_c() {
+ fn_80051190(nullptr);
+ fn_80050EB0(nullptr);
+}
+
+// Ignore the parameter names. I am unsure what they are
+void dLinkage_c::set(u32 flags, f32 x, f32 y, f32 z, void *) {
+ onFlag(0x8000000 | flags);
+ field_0x1C = x;
+ field_0x20 = y;
+ field_0x24 = z;
+
+ if (flags & 2) {
+ field_0x8C = 28.f;
+ field_0x90 = 36.f;
+ field_0x94 = 28.f;
+ field_0x98 = 0.f;
+ } else if (flags & 4) {
+ field_0x8C = 18.f;
+ field_0x90 = 25.f;
+ field_0x94 = 18.f;
+ field_0x98 = 0.f;
+ } else if (flags & 8) {
+ field_0x8C = 16.7f;
+ field_0x90 = 25.f;
+ field_0x94 = 16.7f;
+ field_0x98 = 0.f;
+ } else {
+ field_0x8C = 18.f;
+ field_0x90 = 30.f;
+ field_0x94 = 18.f;
+ field_0x98 = 0.f;
+ }
+}
+
+bool dLinkage_c::tryAttach(
+ dAcObjBase_c *pActor, dAcObjBase_c *pSrc, dAcRefBase_c *pRef, dLinkage_c::ConnectionType_e type, bool replace
+) {
+ if (checkState(STATE_ACTIVE)) {
+ if (replace) {
+ fn_80050EB0(pActor);
+ } else {
+ return false;
+ }
+ }
+ pActor->clearObjectProperty(0x1000);
+ pActor->clearObjectProperty(0x4);
+ mControllingActor.link(pSrc);
+ mState = STATE_ACTIVE;
+ mType = type;
+
+ if (type == CONNECTION_4) {
+ pActor->setObjectProperty(0x4);
+ } else if (type == CONNECTION_7) {
+ pActor->setObjectProperty(0x1000);
+ field_0x1A = 4;
+ }
+ MTXIdentity(carryTransMtx);
+ pLinkedActor = pRef;
+ pRef->link(pActor);
+ if ((pSrc == dAcPy_c::GetLink2() || type == CONNECTION_5) &&
+ pActor->getConnectParent()->profile_name == fProfile::ROOM) {
+ pActor->addActorToRoom(-1);
+ onFlag(0x20000000);
+ pActor->setActorProperty(0x2000000);
+ pActor->changeLoadedEntitiesWithSet();
+ }
+ pActor->clearActorProperty(0x1);
+ return true;
+}
+
+void dLinkage_c::fn_80050DC0(dAcObjBase_c *pActor, const f32 speed, const f32 velocityY, mAng rot) {
+ mState = STATE_2;
+ fn_80050E40(pActor, speed, velocityY, rot);
+}
+
+void dLinkage_c::fn_80050E00(dAcObjBase_c *pActor, const f32 speed, const f32 velocityY, mAng rot) {
+ mState = STATE_3;
+ fn_80050E40(pActor, speed, velocityY, rot);
+}
+
+void dLinkage_c::fn_80050E40(dAcObjBase_c *pActor, const f32 speed, const f32 velocityY, mAng rot) {
+ fn_80050EB0(pActor);
+ pActor->forwardSpeed = speed;
+ pActor->velocity.y = velocityY;
+ pActor->angle.y = rot;
+}
+
+void dLinkage_c::fn_80050EA0(dAcObjBase_c *pActor) {
+ mState = STATE_DELETE;
+ fn_80050EB0(pActor);
+}
+
+void dLinkage_c::fn_80050EB0(dAcObjBase_c *pActor) {
+ mControllingActor.unlink();
+ if (pLinkedActor) {
+ pLinkedActor->unlink();
+ pLinkedActor = nullptr;
+ }
+
+ if (checkType_1_3_5_6_9()) {
+ MTXConcat(carryTransMtx, field_0x58, field_0x58);
+ field_0x58.fn_802F1C40(2, 0);
+ field_0x18 = 5;
+ MTXIdentity(carryTransMtx);
+ } else if (mType == CONNECTION_4) {
+ if (pActor) {
+ pActor->clearObjectProperty(0x4);
+ }
+ } else if (mType == CONNECTION_7) {
+ if (pActor) {
+ pActor->clearObjectProperty(0x1000);
+ }
+ }
+
+ if (pActor && checkFlag(0x20000000)) {
+ pActor->addActorToRoom(pActor->getRoomId());
+ offFlag(0x20000000);
+ }
+
+ field_0x1A = 4;
+ mType = CONNECTION_0;
+ offFlag(0x10000000);
+}
+
+void dLinkage_c::bushTpFunc(dBgS_Acch &acch) {
+ mVec3_c *pos = acch.GetPos();
+ mVec3_c origPos = *pos;
+
+ if (field_0x1A != 0) {
+ if (field_0x1A == 4 && !acch.ChkLineCheck()) {
+ acch.OnLineCheck();
+ onFlag(0x4000000);
+ }
+
+ if (--field_0x1A == 0 && checkFlag(0x4000000)) {
+ acch.OffLineCheck();
+ offFlag(0x4000000);
+ }
+ }
+
+ acch.CrrPos(*dBgS::GetInstance());
+ if (mState == STATE_ACTIVE) {
+ dAcPy_c *player = dAcPy_c::GetLink2();
+ if (mType == CONNECTION_1 && mControllingActor.p_owner == player) {
+ player->fn_80202E00(nullptr, pos->x - origPos.x, pos->z - origPos.z);
+ }
+
+ if (mType == CONNECTION_7 && mControllingActor.p_owner == player) {
+ if (!checkFlag(0x10000)) {
+ if (acch.ChkWallHit(nullptr)) {
+ fn_80050EA0(player->getWhippedItem());
+ return;
+ }
+ field_0x1A = 3;
+ }
+ }
+
+ *pos = origPos;
+ }
+}
+
+void dLinkage_c::fn_80051190(dAcObjBase_c *pActor) {
+ // If not active, return
+ if (!checkState(STATE_ACTIVE)) {
+ return;
+ }
+
+ // If currently Linked
+ if (mControllingActor.p_owner) {
+ // if the actor being linked to is empty, no need to delink
+ if (pLinkedActor == nullptr) {
+ return;
+ }
+
+ // If the Actor is linked to itself, return?
+ dAcObjBase_c *pLinked = static_cast<dAcObjBase_c *>(pLinkedActor->p_owner);
+ if (pLinked && &pLinked->GetLinkage() == this) {
+ return;
+ }
+ }
+ pLinkedActor = nullptr;
+
+ fn_80050EA0(pActor);
+}
+
+void dLinkage_c::fn_800511E0(dAcObjBase_c *pActor) {
+ bool b = checkType_1_3_5_6_9();
+
+ if (!(checkFlag(0x200) || b || field_0x18 == 0)) {
+ field_0x58.slerpTo(mMtx_c::Identity, field_0x58, 1.f / field_0x18);
+ field_0x58.fn_802F1C40(2, 0);
+ field_0x18--;
+ }
+ mMtx_c &mtx = pActor->mWorldMtx;
+ f32 y = field_0x1C * pActor->mScale.y;
+ mtx.transS(pActor->GetPosition().x, pActor->GetPosition().y + pActor->GetYOffset(), pActor->GetPosition().z);
+ if (mType == CONNECTION_1) {
+ MTXConcat(mtx, carryTransMtx, mtx);
+ }
+ mMtx_c m1;
+ MTXTrans(m1, 0.f, y, 0.f);
+ MTXConcat(mtx, m1, mtx);
+
+ if (b && mType != CONNECTION_1) {
+ MTXConcat(mtx, carryTransMtx, mtx);
+ }
+ mMtx_c m2;
+ MTXConcat(mtx, field_0x58, mtx);
+ MTXTrans(m2, 0.f, -y, 0.f);
+ MTXConcat(mtx, m2, mtx);
+
+ mtx.ZXYrotM(pActor->rotation);
+ if (mControllingActor.p_owner) {
+ pActor->roomid = static_cast<dAcObjBase_c *>(mControllingActor.p_owner)->roomid;
+ }
+}
+
+bool dLinkage_c::fn_800513C0() const {
+ return (mState == STATE_ACTIVE && (mType == CONNECTION_1 || mType == CONNECTION_6)) &&
+ !(mControllingActor.p_owner && mControllingActor.p_owner->profile_name == fProfile::E_GEROCK);
+}
diff --git a/src/m/m_mtx.cpp b/src/m/m_mtx.cpp
index 712d612c..521cbb7a 100644
--- a/src/m/m_mtx.cpp
+++ b/src/m/m_mtx.cpp
@@ -1,6 +1,8 @@
+#include "m/m_mtx.h"
+
#include "c/c_math.h"
#include "m/m_math.h"
-#include "nw4r/math.h"
+#include "m/m_vec.h"
void mMtx_c::toRot(mAng3_c &out) const {
f32 t1 = 0.0f;
@@ -10,3 +12,47 @@ void mMtx_c::toRot(mAng3_c &out) const {
}
s16 anglex = cM::atan2s(-m[1][2], t1);
}
+
+void mMtx_c::fn_802F1C40(s32 i, s32 j) {
+ f32 *pJ = &arr[j];
+ f32 *pI = &arr[i];
+
+ mVec3_c v0(pI[0], pI[4], pI[8]);
+ mVec3_c v1(pJ[0], pJ[4], pJ[8]);
+
+ mVec3_c v2;
+ v0.normalize();
+
+ f32 z, y, x;
+ if (j - i == 1 || j - i == -2) {
+ z = (v0.x * v1.y) - (v0.y * v1.x);
+ y = (v0.z * v1.x) - (v0.x * v1.z);
+ x = (v0.y * v1.z) - (v0.z * v1.y);
+ v2 = mVec3_c(x, y, z);
+
+ z = (v2.x * v0.y) - (v2.y * v0.x);
+ y = (v2.z * v0.x) - (v2.x * v0.z);
+ x = (v2.y * v0.z) - (v2.z * v0.y);
+ v1 = mVec3_c(x, y, z);
+ } else {
+ z = (v1.x * v0.y) - (v1.y * v0.x);
+ y = (v1.z * v0.x) - (v1.x * v0.z);
+ x = (v1.y * v0.z) - (v1.z * v0.y);
+ v2 = mVec3_c(x, y, z);
+
+ z = (v0.x * v2.y) - (v0.y * v2.x);
+ y = (v0.z * v2.x) - (v0.x * v2.z);
+ x = (v0.y * v2.z) - (v0.z * v2.y);
+ v1 = mVec3_c(x, y, z);
+ }
+ v2.normalize();
+ v1.normalize();
+
+ f32 *pK = &arr[((3 - i) - j)];
+
+ // clang-format off
+ pI[0] = v0.x; pI[4] = v0.y; pI[8] = v0.z;
+ pJ[0] = v1.x; pJ[4] = v1.y; pJ[8] = v1.z;
+ pK[0] = v2.x; pK[4] = v2.y; pK[8] = v2.z;
+ // clang-format on
+}