summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/d/a/obj/d_a_obj_arrow.cpp894
-rw-r--r--src/toBeSorted/d_sword_swing_effect_mgr.cpp15
2 files changed, 863 insertions, 46 deletions
diff --git a/src/d/a/obj/d_a_obj_arrow.cpp b/src/d/a/obj/d_a_obj_arrow.cpp
index f17c71bc..a52f5daf 100644
--- a/src/d/a/obj/d_a_obj_arrow.cpp
+++ b/src/d/a/obj/d_a_obj_arrow.cpp
@@ -1,11 +1,63 @@
#include "d/a/obj/d_a_obj_arrow.h"
+#include "c/c_lib.h"
#include "c/c_math.h"
+#include "common.h"
+#include "d/a/d_a_item.h"
+#include "d/a/d_a_itembase.h"
+#include "d/a/d_a_player.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/bg/d_bg_s_lin_chk.h"
+#include "d/col/c/c_bg_s_poly_info.h"
#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_angle.h"
+#include "d/d_jnt_col.h"
+#include "d/d_light_env.h"
+#include "d/d_linkage.h"
+#include "d/d_vec.h"
+#include "d/snd/d_snd_source_if.h"
+#include "d/snd/d_snd_wzsound.h"
+#include "f/f_profile_name.h"
+#include "m/m_mtx.h"
+#include "m/m_vec.h"
+#include "nw4r/math/math_types.h"
#include "nw4r/types_nw4r.h"
+#include "s/s_Math.h"
+#include "toBeSorted/d_emitter.h"
SPECIAL_ACTOR_PROFILE(ARROW, dAcArrow_c, fProfile::ARROW, 0x126, 0, 0x80);
+static dBgS_ArrowLinChk sArrowLinChk;
+u16 dAcArrow_c::sCounter;
+
+inline static u32 getDamage1() {
+ return 16;
+}
+
+inline static u32 getDamage2() {
+ return 16;
+}
+
+inline static u32 getDamage3() {
+ return 24;
+}
+
+inline static u32 getDamage4() {
+ return 32;
+}
+
+const u8 dAcArrow_c::sDamageArrMaybe[] = {
+ getDamage1(),
+ getDamage2(),
+ getDamage3(),
+ getDamage4(),
+};
+
STATE_DEFINE(dAcArrow_c, Wait);
STATE_DEFINE(dAcArrow_c, Move);
STATE_DEFINE(dAcArrow_c, ActorStop);
@@ -15,7 +67,7 @@ STATE_DEFINE(dAcArrow_c, Bound);
// clang-format off
cCcD_SrcGObj dAcArrow_c::sCcSrcInf = {
- {AT_TYPE_ARROW, 0x8BB, {0x15,0, 0}, 0, 0, 0, 0, 0, 0},
+ {AT_TYPE_ARROW, 0x8BB, {0x15,0, 0}, sDamageArrMaybe[0], 0, 0, 0, 0, 0},
{
~(AT_TYPE_BUGNET | AT_TYPE_BEETLE | AT_TYPE_GLITTERING_SPORES | AT_TYPE_0x8000 | AT_TYPE_ARROW | AT_TYPE_0x100 | AT_TYPE_WIND | AT_TYPE_SLINGSHOT),
0x210, {0, 0, 0x407}, 0, 0
@@ -45,12 +97,13 @@ bool dAcArrow_atHitCallback(dAcObjBase_c *i_actorA, cCcD_Obj *i_objInfA, dAcObjB
bool dAcArrow_c::createHeap() {
mResFile = nw4r::g3d::ResFile(getOarcResFile("Alink"));
nw4r::g3d::ResMdl mdl(nullptr);
- if ((mSubType & 0x10) != 0) {
+ if ((isSlingshotProjectile()) != 0) {
mdl = mResFile.GetResMdl("EquipPachinkoBullet");
} else {
mdl = mResFile.GetResMdl("EquipArrow");
}
- // ?
+ // Looks weird; the more likely explanation here is that they did an `if (!create) return false;`
+ // forgetting the `return true;` case, but this matches without UB so let's keep it that way?
bool ok = mModel.create(mdl, &mAllocator, 0x120);
if (!ok) {
ok = false;
@@ -58,22 +111,20 @@ bool dAcArrow_c::createHeap() {
return ok;
}
-extern "C" void fn_8025E5E0(void *);
-
int dAcArrow_c::create() {
- mSubType = mParams & 0xFF;
+ mArrowType = mParams & 0xFF;
CREATE_ALLOCATOR(dAcArrow_c);
- field_0x67C |= 4;
+ setArrowFlag(ARROW_INITIAL_SPAWN);
mStts.SetRank(2);
mCcCps.Set(sCc1);
mCcCps.SetStts(mStts);
- mCcCps.SetAtFlag(0x2000);
+ mCcCps.OnAt_0x2000();
mCcCps.SetAtCallback(dAcArrow_atHitCallback);
mCcSph.Set(sCc2);
mCcSph.SetStts(mStts);
- if (mSubType == 0x11) {
+ if (mArrowType == 17) {
mStateMgr.changeState(StateID_Move);
} else {
mStateMgr.changeState(StateID_Wait);
@@ -82,52 +133,827 @@ int dAcArrow_c::create() {
mBoundingBox.Set(mVec3_c(-6.0f, -6.0f, 0.0f), mVec3_c(6.0f, 6.0f, 110.0f));
field_0x684 = -1;
field_0x68A = 300;
- f32 rnd = cM::rndF(20.0f);
- field_0x688 = 50.0f - rnd;
+ field_0x688 = 50.0f - cM::rndF(20.0f);
field_0x6A8 = 80.0f;
mDespawnTimer = 10;
- fn_8025E5E0(this);
+ updateRoomId();
return SUCCEEDED;
}
dAcArrow_c::~dAcArrow_c() {}
-void dAcArrow_c::hitCallback(cCcD_Obj *i_objInfA, dAcObjBase_c *i_actorB, cCcD_Obj *i_objInfB) {}
+void dAcArrow_c::hitCallback(cCcD_Obj *i_objInfA, dAcObjBase_c *i_actorB, cCcD_Obj *i_objInfB) {
+ dJntCol_c *col = i_actorB->getLinkage().getJntCol();
+ if (col != nullptr) {
+ field_0x698 = col->getArrowOffsetPosAndAngle(
+ &i_objInfA->GetAtHitPos(), &mRotation, &field_0x6B0, &field_0x6BC, i_objInfB->ChkTg_0x4C(0x2000)
+ );
-int dAcArrow_c::doDelete() {
- // TODO
+ if (field_0x698 >= 0) {
+ mRef1.link(i_actorB);
+ } else {
+ mRef1.unlink();
+ }
+ }
+}
- return SUCCEEDED;
+bool dAcArrow_c::fn_8025DD20(const mVec3_c &v1, mVec3_c &v2, bool noEffect) {
+ if (dBgS_WtrLinChk::SetIsWater(&v1, &v2, this)) {
+ const mVec3_c &end = dBgS_WtrLinChk::GetInstance().GetLinEnd();
+ if (isSlingshotProjectile()) {
+ v2 = end;
+ } else {
+ mVec3_c t1 = v2 - end;
+ f32 sc;
+ f32 dist = v2.distance(v1);
+ if (dist > 0.0001f) {
+ sc = t1.mag() / dist;
+ } else {
+ sc = 1.0f;
+ }
+ t1.normalize();
+ v2 = end + t1 * field_0x6A8 * sc;
+ }
+
+ if (!noEffect) {
+ dAcPy_c::fn_801E2FC0(end, dBgS_WtrLinChk::GetInstance(), 0.5f);
+ startSound(SE_AW_HIT_WATER);
+ }
+ return true;
+ }
+
+ return false;
}
-int dAcArrow_c::actorExecute() {
- mStateMgr.executeState();
+void dAcArrow_c::fn_8025DED0(f32 f) {
+ f32 f1;
+ dAcPy_c *link = dAcPy_c::GetLink2();
+ if (isSlingshotProjectile()) {
+ f1 = 12.0f;
+ } else {
+ f1 = 5.0f;
+ f32 f2 = link->fn_802097C0();
+ if (f > f2) {
+ f32 f3 = link->fn_802097D0();
+ if (f3 <= f2) {
+ f1 += link->fn_802097B0();
+ } else {
+ f32 f4 = (f - f2) / (f3 - f2);
+ if (f4 > 1.0f) {
+ f4 = 1.0f;
+ }
+ f1 += f4 * link->fn_802097B0();
+ }
+ }
+ }
- // TODO
+ mVec3_c next = mVec3_c(mPosition + mVelocity * (field_0x6A0 + 1.0f));
+ mCcCps.OnAtSet();
- return SUCCEEDED;
+ if (!checkArrowFlag(ARROW_0x20)) {
+ if (!isSlingshotProjectile()) {
+ holdSound(SE_AW_FLY_LV);
+ }
+ fb:
+ fn_8025DD20(mPosition, next, true);
+ } else {
+ f32 diff = next.y - field_0x6D4.y;
+ if (diff < -300.0f) {
+ diff = -300.0f - diff;
+ f32 diff2 = next.y - mPosition.y;
+ diff2 = nw4r::math::FAbs(diff2);
+ if (diff2 > diff) {
+ next = mPosition + mVelocity * ((field_0x6A0 + 1.0f) * ((diff2 - diff) / diff2));
+ }
+ }
+ }
+
+ sArrowLinChk.Set(&mPosition, &next, this);
+ if (dBgS::GetInstance()->LineCross(&sArrowLinChk)) {
+ next = sArrowLinChk.GetLinEnd();
+ }
+ mCcCps.Set(mPosition, next, f1);
+ mCcCps.unknownCalc();
+ dCcS::GetInstance()->Set(&mCcCps);
+ dCcS::GetInstance()->GetMassMng().SetObj(&mCcCps, 1);
}
-int dAcArrow_c::draw() {
- return SUCCEEDED;
+void dAcArrow_c::fn_8025E160() {
+ // NONMATCHING
+ dAcPy_c *link = dAcPy_c::GetLink2();
+ if (isSlingshotProjectile()) {
+ field_0x6A0 = 0.0f;
+ if (mArrowType != 17) {
+ // TODO - this inline is not certain anyway...
+ setRotXY(mAngle, -link->getField_0x1268(), link->getField_0x126A() + link->getRotation().y);
+ } else {
+ mAngle.y = mRotation.y;
+ mAngle.x = -mRotation.x;
+ }
+ link->fn_80209700(field_0x6A4, field_0x69C, false);
+ } else {
+ link->fn_80209700(field_0x6A4, field_0x69C, false);
+ if (checkArrowFlag(ARROW_0x80)) {
+ const mVec3_c *v = link->fn_802097E0(mRotation.x, mRotation.y);
+ if (v != nullptr) {
+ mPosition = *v;
+ mAngle.x = -mRotation.x;
+ mAngle.y = mRotation.y;
+ }
+ }
+ field_0x683 = 30;
+ field_0x6A0 = 90.0f / field_0x69C;
+ startSound(SE_AW_FLY);
+ }
+
+ if (checkArrowFlag(ARROW_0x40)) {
+ unsetArrowFlag(ARROW_0x40);
+ mVec3_c tmp = field_0x6EC - mPosition;
+ mAngle.x = tmp.atan2sY_XZ() + field_0x6AC * cM::rndFX(400.0f);
+ mAngle.y = tmp.atan2sX_Z() + field_0x6AC * cM::rndFX(400.0f);
+ mRotation.x = -mAngle.x;
+ mRotation.y = mAngle.y;
+ }
+
+ // Spawn additional projectiles for Mighty Scattershot
+ if (isSlingshotProjectile() && checkArrowFlag(ARROW_0x80)) {
+ mVec3_c tmp = mVec3_c::Ez;
+ tmp.rotX(mAngle.x);
+ tmp.rotY(mAngle.y);
+
+ mAng3_c ang(0, 0, 0);
+
+ for (int i = 0; i < 8; i++) {
+ mVec3_c tmp2 = mVec3_c::Ez;
+ // TODO eliminate temps?
+ mAng a1 = link->fn_80208CA0();
+ mAng a2 = mAng::fromDeg(cM::rndF(2.5f));
+ tmp2.rotX(mAngle.x + a1 - a2);
+ tmp2.rotY(mAngle.y);
+
+ mMtx_c mtx;
+ mtx.setAxisRotation(tmp, i * mAng::s2r_c(0x2000) + mAng::d2r_c(cM::rndF(2.5f)));
+ MTXMultVecSR(mtx, tmp2, tmp2);
+ ang.x = tmp2.atan2sY_XZ();
+ ang.y = tmp2.atan2sX_Z();
+ dAcObjBase_c::create(fProfile::ARROW, -1, 17, &mPosition, &ang, 0, -1);
+ }
+ }
+
+ mSpeed = 100.0f;
+ field_0x6C8 = mPosition;
+ mVelocity.fromXY(mAngle.x, mAngle.y, field_0x69C);
+ if (!isSlingshotProjectile()) {
+ field_0x684 = sCounter;
+ sCounter++;
+ if (sCounter == 6) {
+ sCounter = 0;
+ }
+ }
+ fn_8025DED0(0.0f);
+}
+
+void dAcArrow_c::updateRoomId() {
+ if (dBgS_ObjGndChk::CheckPos(mPosition)) {
+ mRoomID = dBgS_ObjGndChk::GetRoomID();
+ } else if (mRoomID == -1) {
+ mRoomID = dAcPy_c::GetLink2()->getRoomId();
+ }
+}
+
+s16 dAcArrow_c::fn_8025E640() {
+ if (sLib::calcTimer(&field_0x688)) {
+ field_0x690 += (s16)(21243.0f - cM::rndF(0x1000));
+ f32 a = field_0x688 * 0.02f;
+ return a * 0x400 * a * field_0x690.sin();
+ } else {
+ return 0;
+ }
+}
+
+void dAcArrow_c::fn_8025E720(dAcObjBase_c *obj, const mVec3_c &v) {
+ // NONMATCHING
+ mRef1.link(obj);
+ mMtx_c mtx;
+ // TODO argument order
+ mtx.inverseTo(obj->mWorldMtx);
+ MTXMultVec(mtx, v, field_0x6B0);
+ mVec3_c v1 = mVec3_c::createProjectionXZ(mRotation, 1.0f);
+ v1.y *= -1.0f;
+ MTXMultVecSR(mtx, v1, field_0x6BC);
+}
+
+void dAcArrow_c::updateMtx() {
+ mWorldMtx.transS(mPosition);
+ mWorldMtx.XYZrotM(mRotation);
+ if (mStateMgr.isState(StateID_BgStop)) {
+ mMtx_c mtx;
+ mtx.transS(0.0f, 0.0f, -90.0f);
+ MTXConcat(mWorldMtx, mtx, mWorldMtx);
+ } else if (mStateMgr.isState(StateID_Bound)) {
+ mMtx_c mtx;
+ mtx.transS(0.0f, 0.0f, -45.0f);
+ MTXConcat(mWorldMtx, mtx, mWorldMtx);
+ }
+ mModel.setLocalMtx(mWorldMtx);
+}
+
+void dAcArrow_c::setInitialPosition() {
+ dAcPy_c::GetLink2()->getWeaponLMtx(mWorldMtx);
+ mModel.setLocalMtx(mWorldMtx);
+ mWorldMtx.getTranslation(mPosition);
+ mWorldMtx.toRot(mRotation);
+ mAngle.y = mRotation.y;
+ mAngle.x = -mRotation.x;
+}
+
+dAcObjBase_c *dAcArrow_c::fn_8025E960() {
+ s16 a1 = fn_8025E640();
+ dAcObjBase_c *o1 = mRef1.get();
+ if (o1 == nullptr || o1->checkObjectProperty(OBJ_PROP_0x100)) {
+ return nullptr;
+ } else if (checkArrowFlag(ARROW_0x2000)) {
+ if (checkArrowFlag(ARROW_0x10000)) {
+ mWorldMtx.getTranslation(mPosition);
+ mWorldMtx.toRot(mRotation);
+ mMtx_c mtx;
+ mtx.transS(0.0f, 0.0f, -90.0f);
+ MTXConcat(mWorldMtx, mtx, mWorldMtx);
+ mModel.setLocalMtx(mWorldMtx);
+ }
+ return o1;
+ } else {
+ dJntCol_c *col = o1->getLinkage().getJntCol();
+ if (col != nullptr) {
+ col->setArrowPosAndAngle(&field_0x6B0, &field_0x6BC, field_0x698, &mPosition, &mRotation);
+ } else {
+ MTXMultVec(o1->mWorldMtx, field_0x6B0, mPosition);
+ mVec3_c tmp;
+ MTXMultVecSR(o1->mWorldMtx, field_0x6BC, tmp);
+ mRotation.x = tmp.atan2snY_XZ();
+ mRotation.y = tmp.atan2sX_Z();
+ }
+ mWorldMtx.transS(mPosition);
+ mWorldMtx.ZXYrotM(mRotation.x + a1, mRotation.y, mRotation.z);
+ mMtx_c mtx;
+ mtx.transS(0.0f, 0.0f, -90.0f);
+ MTXConcat(mWorldMtx, mtx, mWorldMtx);
+ mModel.setLocalMtx(mWorldMtx);
+ return o1;
+ }
+}
+
+void dAcArrow_c::initPickupCc() {
+ mCcSph.SetR(25.0f);
+ mCcSph.ClrTgSet();
+ mCcSph.OnCoSet();
+}
+
+bool dAcArrow_c::checkPickup() {
+ if (dAcPy_c::getCurrentBowType() != 0) {
+ if (mCcSph.ChkCoHit()) {
+ dAcItem_c::giveItem(ITEM_SINGLE_ARROW, 0, -1);
+ setArrowFlag(ARROW_0x2);
+ return true;
+ }
+ mCcSph.SetC(mPosition);
+ dCcS::GetInstance()->Set(&mCcSph);
+ }
+
+ return false;
+}
+
+void dAcArrow_c::initializeState_Wait() {
+ setInitialPosition();
+}
+
+void dAcArrow_c::executeState_Wait() {
+ setInitialPosition();
+ if (checkArrowFlag(ARROW_0x800)) {
+ mStateMgr.changeState(StateID_Move);
+ } else if (isSlingshotProjectile()) {
+ field_0x681 = 1;
+ }
}
-void dAcArrow_c::initializeState_Wait() {}
-void dAcArrow_c::executeState_Wait() {}
void dAcArrow_c::finalizeState_Wait() {}
-void dAcArrow_c::initializeState_Move() {}
-void dAcArrow_c::executeState_Move() {}
+void dAcArrow_c::initializeState_Move() {
+ setArrowFlag(ARROW_0x1000);
+ setActorProperty(AC_PROP_0x4);
+ if (isSlingshotProjectile()) {
+ mCcCps.SetAtType(AT_TYPE_SLINGSHOT);
+ mCcCps.SetAtInfo_0x0(20);
+ mCcCps.SetAtDamage(0);
+ mEffectId = PARTICLE_RESOURCE_ID_MAPPING_207_;
+ } else {
+ u8 dmg = sDamageArrMaybe[dAcPy_c::getCurrentBowType()];
+ if (checkArrowFlag(ARROW_0x80)) {
+ mCcCps.SetAtFlagsUpper(0x2000000);
+ mEffectId = PARTICLE_RESOURCE_ID_MAPPING_2_;
+ dmg = (s32)dmg * 1.5f + 0.5f;
+ } else {
+ mEffectId = PARTICLE_RESOURCE_ID_MAPPING_1_;
+ }
+ mCcCps.SetAtDamage(dmg);
+ mCcCps.OnAt_0x1000();
+ }
+ mCcCps.OnTgSet();
+ fn_8025E160();
+ updateMtx();
+}
+
+void dAcArrow_c::executeState_Move() {
+ mPosition += mVelocity;
+ mVec3_c next = mVec3_c(mPosition + mVelocity * field_0x6A0);
+ if (!checkArrowFlag(ARROW_0x20)) {
+ sArrowLinChk.Set(&mOldPosition, &next, this);
+ mVec3_c t;
+ if (dBgS::GetInstance()->LineCross(&sArrowLinChk)) {
+ t = sArrowLinChk.GetLinEnd();
+ } else {
+ t = next;
+ }
+
+ if (fn_8025DD20(mOldPosition, t, false)) {
+ setArrowFlag(ARROW_0x20);
+ unsetArrowFlag(ARROW_0x200);
+ field_0x6D4 = dBgS_WtrLinChk::GetInstance().GetLinEnd();
+ mVelocity.normalize();
+ mPosition = t - mVelocity * 90.0f;
+ mVelocity *= field_0x6A8;
+
+ if (!isSlingshotProjectile()) {
+ field_0x6A0 = 90.0f / field_0x6A8;
+ }
+ next = t;
+ }
+ }
+
+ sArrowLinChk.Set(&mOldPosition, &next, this);
+ bool isCross = dBgS::GetInstance()->LineCross(&sArrowLinChk);
+ // TODO the constness here is probably a bit messed up
+ const cCcD_Obj *obj = nullptr;
+ s32 flags = -1;
+ if (mCcCps.ChkTgHit()) {
+ obj = &mCcCps;
+ }
+
+ if (obj != nullptr) {
+ flags = obj->GetTgDamageFlags();
+ }
+
+ // TODO magic numbers
+ if (flags == 8) {
+ mPosition = obj->GetTgHitPos();
+ const mVec3_c &hitDir = obj->GetTgAtHitDir();
+ if (hitDir.squareMagXZ() < 1.0f) {
+ // TODO constness
+ mAngle.y = cLib::targetAngleY(mPosition, const_cast<cCcD_Obj *>(obj)->GetTgActor()->mPosition);
+ } else {
+ mAngle.y = hitDir.atan2snX_nZ();
+ }
+
+ mRotation.y = mAngle.y;
+ setArrowFlag(ARROW_0x400);
+ mStateMgr.changeState(StateID_Bound);
+ } else if (obj != nullptr) {
+ mPosition = obj->GetTgHitPos();
+ mStateMgr.changeState(StateID_Bound);
+ startSound(SE_AW_FLIP);
+ } else {
+ dAcObjBase_c *atActor;
+ s32 what;
+
+ if (mCcCps.ChkAtHit()) {
+ if (mCcCps.GetAtActor()->mProfileName == fProfile::PUMPKIN) {
+ field_0x683 = 0;
+ }
+ dLightEnv_c::GetPInstance()->setBPM8_Type6(&mCcCps.GetAtHitPos());
+ if (isSlingshotProjectile()) {
+ fn_80260050(mCcCps.GetAtHitPos(), 0);
+ return;
+ }
+ atActor = mCcCps.GetAtActor();
+ what = 1;
+ if (atActor != nullptr && atActor->getLinkage().hasJntCol()) {
+ bool b = false;
+ if (atActor != mRef1.get()) {
+ field_0x698 = atActor->getLinkage().getArrowOffsetPosAndAngle(
+ &mCcCps.GetAtHitPos(), &mRotation, &field_0x6B0, &field_0x6BC, mCcCps.GetAtFlag0x2()
+ );
+ b = true;
+ }
+
+ if (field_0x698 >= 0) {
+ what = 4;
+ if (b) {
+ mRef1.link(atActor);
+ }
+ } else if (field_0x698 == -2 || mCcCps.GetAtFlag0x2()) {
+ what = 2;
+ }
+ } else {
+ if (mCcCps.GetAtFlag0x2()) {
+ what = 2;
+ } else if (mCcCps.ChkAtArrowStick()) {
+ fn_8025E720(atActor, mCcCps.GetAtHitPos());
+ what = 4;
+ }
+ }
+
+ if (what == 1 && atActor != nullptr && atActor->getLinkage().checkFlag(0x1000) &&
+ !isSlingshotProjectile()) {
+ if (!mRef2.isLinked()) {
+ atActor->getLinkage().tryAttach(atActor, this, &mRef2, dLinkage_c::CONNECTION_8, false);
+ }
+ what = 0;
+ }
+ } else {
+ what = 0;
+ }
+
+ switch (what) {
+ default: {
+ if (what == 2) {
+ if (checkArrowFlag(ARROW_0x20)) {
+ setArrowFlag(ARROW_0x2);
+ } else {
+ if (mCcCps.ChkAtHit()) {
+ mPosition = mCcCps.GetAtHitPos();
+ }
+ mStateMgr.changeState(StateID_Bound);
+ }
+ } else if (what == 4) {
+ mStateMgr.changeState(StateID_ActorStop);
+ } else {
+ setArrowFlag(ARROW_0x2);
+ if (!checkArrowFlag(ARROW_0x20) && mCcCps.ChkAtHit()) {
+ mPosition = mCcCps.GetAtHitPos();
+ }
+ }
+ break;
+ }
+ case 0:
+ case 3: {
+ if (isCross) {
+ mPosition = sArrowLinChk.GetLinEnd();
+ if (checkArrowFlag(ARROW_0x20) &&
+ (isSlingshotProjectile() || mPosition.y - field_0x6D4.y < -300.0f)) {
+ setArrowFlag(ARROW_0x2);
+ } else {
+ s32 polyAtt0 = dBgS::GetInstance()->GetPolyAtt0(sArrowLinChk);
+ s32 polyAtt1 = dBgS::GetInstance()->GetPolyAtt1(sArrowLinChk);
+ s32 specialCode = dBgS::GetInstance()->GetSpecialCode(sArrowLinChk);
+ if (isSlingshotProjectile() || specialCode == 19 || specialCode == 20 || specialCode == 16 ||
+ specialCode == 10 || specialCode == 11 || polyAtt0 == 6 || polyAtt0 == POLY_ATT_0_ROCK ||
+ polyAtt0 == POLY_ATT_0_NONE || polyAtt0 == POLY_ATT_0_NUMA ||
+ polyAtt0 == POLY_ATT_0_STONE || polyAtt0 == POLY_ATT_0_METAL ||
+ (polyAtt0 == POLY_ATT_0_LIFE && (polyAtt1 == 2 || polyAtt1 == 3))) {
+ if (checkArrowFlag(ARROW_0x20)) {
+ setArrowFlag(ARROW_0x2);
+ } else {
+ dAcPy_c::fn_801E2FC0(mPosition, sArrowLinChk, 0.5f);
+ if (isSlingshotProjectile()) {
+ fn_80260050(mPosition, polyAtt0 == POLY_ATT_0_LAVA);
+ } else {
+ startBgHitSound(SE_AW_HIT, sArrowLinChk, nullptr);
+ if (polyAtt0 == POLY_ATT_0_LAVA || polyAtt0 == POLY_ATT_0_NUMA ||
+ polyAtt0 == POLY_ATT_0_NONE || specialCode == 16 || specialCode == 10 ||
+ specialCode == 11) {
+ setArrowFlag(ARROW_0x2);
+ } else {
+ mStateMgr.changeState(StateID_Bound);
+ }
+ }
+ }
+ } else {
+ mStateMgr.changeState(StateID_BgStop);
+ }
+ }
+ } else if (checkArrowFlag(ARROW_0x20)) {
+ if (isSlingshotProjectile()) {
+ mPosition = next;
+ setArrowFlag(ARROW_0x2);
+ } else {
+ f32 diff = mPosition.y - field_0x6D4.y;
+ if (diff < -300.0f) {
+ mCcCps.ClrAtSet();
+ mCcCps.ClrAtHit();
+ if (sLib::chase(&mScale.x, 0.0f, 0.1f)) {
+ setArrowFlag(ARROW_0x2);
+ } else {
+ mScale.y = mScale.z = mScale.x;
+ mModel.setScale(mScale);
+ }
+ } else if (diff > 90.0f) {
+ setArrowFlag(ARROW_0x2);
+ } else {
+ fn_8025DED0(mPosition.distance(field_0x6C8));
+ }
+ }
+ } else {
+ f32 diff = mPosition.distance(field_0x6C8);
+ if (diff > field_0x6A4 || mAcceleration < 0.0f) {
+ if (isSlingshotProjectile()) {
+ mAcceleration = -5.0f;
+ } else {
+ mAcceleration = -2.0f;
+ }
+ mVelocity.y += mAcceleration;
+ if (isSlingshotProjectile()) {
+ dAcPy_c *link = dAcPy_c::GetLink2();
+ f32 xz = mVelocity.absXZ();
+ f32 t1 = link->fn_80208CE0();
+ if (xz > t1) {
+ f32 orig = xz;
+ sLib::chase(&xz, t1, link->fn_80208CF0());
+ xz /= orig;
+ mVelocity.x *= xz;
+ mVelocity.z *= xz;
+ }
+ }
+ if (field_0x68A != 0) {
+ field_0x68A--;
+ } else {
+ setArrowFlag(ARROW_0x2);
+ return;
+ }
+ mRotation.x = mVelocity.atan2snY_XZ();
+ mAngle.x = -mRotation.x;
+ if (!isSlingshotProjectile()) {
+ field_0x6A0 = 90.0f / mVelocity.mag();
+ }
+ }
+ fn_8025DED0(diff);
+ }
+ break;
+ }
+ }
+ }
+}
+
void dAcArrow_c::finalizeState_Move() {}
-void dAcArrow_c::initializeState_ActorStop() {}
-void dAcArrow_c::executeState_ActorStop() {}
-void dAcArrow_c::finalizeState_ActorStop() {}
+void dAcArrow_c::initializeState_Bound() {
+ if (isSlingshotProjectile()) {
+ fn_80260050(mPosition, false);
+ } else {
+ mSpeed = 0.0f;
+ fn_802601C0();
+ f32 rnd = cM::rndFX(0x2000);
+ f32 ang = mAngle.y + 0x8000;
+ mAng ay = ang + rnd;
+ mAng ax;
+ if (checkArrowFlag(ARROW_0x400)) {
+ ax = 0x2000 - cM::rndF(0x1000);
+ } else {
+ ax = -cM::rndF(0x1000);
+ }
+ mVelocity.fromXY(ax, ay, 15.0f + cM::rndF(15.0f));
+ field_0x690 = 0x2C00 - cM::rndF(0x1000);
+ setArrowFlag(ARROW_0x100);
+ unsetArrowFlag(ARROW_0x200);
+ updateMtx();
+ }
+}
-void dAcArrow_c::initializeState_BgStop() {}
-void dAcArrow_c::executeState_BgStop() {}
-void dAcArrow_c::finalizeState_BgStop() {}
+void dAcArrow_c::executeState_Bound() {
+ mVelocity.y -= 2.0f;
+ mPosition += mVelocity;
+ mRotation.x += field_0x690;
+
+ mVec3_c next = mPosition + mVelocity * field_0x6A0;
+
+ sArrowLinChk.Set(&mOldPosition, &next, this);
+ if (dBgS::GetInstance()->LineCross(&sArrowLinChk)) {
+ cM3dGPla pla;
+ dBgS::GetInstance()->GetTriPla(sArrowLinChk, &pla);
+ f32 halfMag = mVelocity.mag() * 0.5f;
+
+ VECReflect(mVelocity, pla.mNormal, mVelocity);
+ mVelocity *= halfMag;
+ field_0x690.mVal >>= 1;
+ if (dBgS_CheckBGroundPoly(sArrowLinChk)) {
+ setArrowFlag(ARROW_0x1);
+ }
+ } else if ((checkArrowFlag(ARROW_0x1) && mVelocity.y <= 0.0f) || field_0x6C8.y - 5000.0f > mPosition.y) {
+ setArrowFlag(ARROW_0x2);
+ }
+
+ updateMtx();
+}
-void dAcArrow_c::initializeState_Bound() {}
-void dAcArrow_c::executeState_Bound() {}
void dAcArrow_c::finalizeState_Bound() {}
+
+void dAcArrow_c::initializeState_BgStop() {
+ fn_802601C0();
+ cM3dGPla pla;
+ dBgS::GetInstance()->GetTriPla(sArrowLinChk, &pla);
+ mVec3_c vz;
+ mWorldMtx.getBase(2, vz);
+ if (pla.mNormal.dot(vz) > mAng(19115).cos()) {
+ mVec3_c c;
+ vecCross(c, pla.mNormal, vz);
+ if (nw4r::math::VEC3LenSq(c) > 0.1f) {
+ mMtx_c mtx;
+ mtx.setAxisRotation(c, mAng::s2r_c(19115));
+ MTXMultVecSR(mtx.m, pla.mNormal, vz);
+ mRotation.y = vz.atan2sX_Z();
+ mRotation.x = vz.atan2snY_XZ();
+ }
+ }
+
+ unsetArrowFlag(ARROW_0x200);
+ setArrowFlag(ARROW_0x100);
+ mSpeed = 0.0f;
+ mAngle.x = -mRotation.x;
+ field_0x68A = 300;
+ updateMtx();
+ mPolyInfo.SetPolyInfo(sArrowLinChk);
+ startBgHitSound(SE_AW_STICK, sArrowLinChk, nullptr);
+ // TODO - constness
+ dBgS::GetInstance()->ArrowStickCallBack(sArrowLinChk, this, const_cast<mVec3_c &>(sArrowLinChk.GetLinEnd()));
+ initPickupCc();
+ dLightEnv_c::GetPInstance()->setBPM8_Type6(&mPosition);
+ const dAcObjBase_c *ac = dBgS::GetInstance()->GetActorPointer(sArrowLinChk);
+ if (ac != nullptr) {
+ // TODO - constness
+ fn_8025E720(const_cast<dAcObjBase_c *>(ac), mPosition);
+ setArrowFlag(ARROW_0x8000);
+ }
+}
+
+void dAcArrow_c::executeState_BgStop() {
+ checkPickup();
+ dAcObjBase_c *ref = this;
+ if (checkArrowFlag(ARROW_0x8000)) {
+ ref = fn_8025E960();
+ }
+
+ if (checkArrowFlag(ARROW_0x10) || ref == nullptr ||
+ ((!ref->checkObjectProperty(OBJ_PROP_0x10000) || !checkArrowFlag(ARROW_0x8000)) &&
+ !dBgS::GetInstance()->ChkPolySafe(mPolyInfo))) {
+ setArrowFlag(ARROW_0x2);
+ } else if (!checkArrowFlag(ARROW_0x8000)) {
+ bool b = false;
+ s16 s1 = fn_8025E640();
+ if (field_0x688 != 0) {
+ b = true;
+ }
+ if (dBgS::GetInstance()->ChkMoveBG(mPolyInfo, true)) {
+ dBgS::GetInstance()->MoveBgTransPos(mPolyInfo, true, &mPosition, &mAngle, &mRotation);
+ b = true;
+ }
+
+ if (b != 0) {
+ mRotation.x = s1 - mAngle.x;
+ updateMtx();
+ }
+ }
+}
+
+void dAcArrow_c::finalizeState_BgStop() {}
+
+void dAcArrow_c::initializeState_ActorStop() {
+ fn_802601C0();
+ unsetArrowFlag(ARROW_0x200);
+ mSpeed = 0.0f;
+ dAcObjBase_c *obj = fn_8025E960();
+ if (obj != nullptr) {
+ getSoundSource()->startObjHitSound(SE_AW_STICK, obj->getSoundSource(), mPosition);
+ }
+ initPickupCc();
+}
+
+void dAcArrow_c::executeState_ActorStop() {
+ dAcObjBase_c *obj = fn_8025E960();
+ checkPickup();
+ if (checkArrowFlag(ARROW_0x10) || obj == nullptr) {
+ setArrowFlag(ARROW_0x2);
+ }
+ unsetArrowFlag(ARROW_0x10000);
+}
+
+void dAcArrow_c::finalizeState_ActorStop() {
+ unsetArrowFlag(ARROW_0x10000);
+}
+
+void dAcArrow_c::fn_80260050(const mVec3_c &v, bool b) {
+ if (b) {
+ startSound(SE_PC_HIT_LAVA);
+ } else {
+ startSound(SE_PC_HIT);
+ }
+ setArrowFlag(ARROW_0x2);
+ setArrowFlag(ARROW_0x100);
+ dJEffManager_c::spawnEffect(PARTICLE_RESOURCE_ID_MAPPING_538_, v, nullptr, nullptr, nullptr, nullptr, 0, 0);
+}
+
+void dAcArrow_c::fn_802600D0(bool b) {
+ // NONMATCHING
+ if (b) {
+ mWorldMtx.getTranslation(field_0x6E0);
+ field_0x692.x.mVal = 0;
+ field_0x692.y.mVal = mRotation.y;
+ field_0x692.z.mVal = field_0x68E;
+ if (mEffectId == PARTICLE_RESOURCE_ID_MAPPING_2_) {
+ field_0x68E += 0x888;
+ }
+ mMtx_c mtx;
+ mtx.transS(field_0x6E0);
+ mtx.ZXYrotM(field_0x692);
+ mEffects.holdEffect(mEffectId, mtx, nullptr, nullptr);
+ } else {
+ mEffects.setFading(5);
+ unsetArrowFlag(ARROW_0x1000);
+ }
+ unsetArrowFlag(ARROW_0x100);
+}
+
+void dAcArrow_c::fn_802601C0() {
+ if (field_0x683 != 0) {
+ if (!(mCcCps.ChkAtHit() && mCcCps.GetAtActor()->mProfileName == fProfile::PUMPKIN)) {
+ setArrowFlag(ARROW_0x4000);
+ }
+ field_0x683 = 0;
+ }
+}
+
+bool dAcArrow_c::fn_80260250(dAcObjBase_c *o1, dAcObjBase_c *o2) {
+ dAcObjBase_c *o = mRef2.get();
+ if (o == nullptr || o1 == o) {
+ o1->getLinkage().forceRemove(o1);
+ o2->getLinkage().tryAttach(o2, this, &mRef2, dLinkage_c::CONNECTION_8, false);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+int dAcArrow_c::actorExecute() {
+ unsetArrowFlag(ARROW_0x4000);
+ if (field_0x683 != 0) {
+ field_0x683--;
+ if (field_0x683 == 0) {
+ setArrowFlag(ARROW_0x4000);
+ }
+ }
+
+ if (checkArrowFlag(ARROW_0x2)) {
+ // TODO - works but maybe temps or inlines?
+ if (mRef2.isLinked()) {
+ mRef2.get()->getLinkage().forceRemove(mRef2.get());
+ }
+ fn_802601C0();
+ if (mDespawnTimer != 0) {
+ mDespawnTimer--;
+
+ } else {
+ deleteRequest();
+ return SUCCEEDED;
+ }
+ } else {
+ if (field_0x684 == sCounter) {
+ setArrowFlag(ARROW_0x10);
+ }
+ if (field_0x681 != 0) {
+ field_0x681--;
+ }
+ mStateMgr.executeState();
+ if (mStateMgr.isState(StateID_Move)) {
+ updateMtx();
+ }
+ }
+
+ mPositionCopy2 = mPositionCopy3 = mPosition;
+ if (checkArrowFlag(ARROW_0x1000)) {
+ fn_802600D0(mStateMgr.isState(StateID_Move) && !checkArrowFlag(ARROW_0x2) || checkArrowFlag(ARROW_0x100));
+ }
+ updateRoomId();
+ dAcObjBase_c *obj = mRef2.get();
+ if (obj != nullptr) {
+ static const mVec3_c v(0.0f, 0.0f, 45.0f);
+ mVec3_c v2;
+ MTXMultVec(mWorldMtx, v, v2);
+ obj->mPosition = v2;
+ obj->mPosition.y -= obj->getLinkage().getField_0x1C();
+ }
+
+ return SUCCEEDED;
+}
+
+int dAcArrow_c::draw() {
+ if (field_0x681 != 0) {
+ return SUCCEEDED;
+ }
+ if (checkArrowFlag(ARROW_0x2)) {
+ return SUCCEEDED;
+ }
+ if (mStateMgr.isState(StateID_Wait) && checkArrowFlag(ARROW_INITIAL_SPAWN)) {
+ setInitialPosition();
+ unsetArrowFlag(ARROW_INITIAL_SPAWN);
+ }
+ drawModelType1(&mModel);
+ return SUCCEEDED;
+}
diff --git a/src/toBeSorted/d_sword_swing_effect_mgr.cpp b/src/toBeSorted/d_sword_swing_effect_mgr.cpp
index 1d0339c3..b1558788 100644
--- a/src/toBeSorted/d_sword_swing_effect_mgr.cpp
+++ b/src/toBeSorted/d_sword_swing_effect_mgr.cpp
@@ -3,16 +3,7 @@
#include "c/c_math.h"
#include "egg/math/eggMatrix.h"
#include "m/m_vec.h"
-
-// TODO: can't use EGG::Vector3f::cross because the Vector3f -> mVec3_c conversion
-// forces additional stack stores. An open-coded cross function works too in this
-// file but maybe pattern comes up in more files and then we can move it to d_vec?
-inline void cross(mVec3_c &result, const mVec3_c &left, const mVec3_c &right) {
- result.set(
- (left.y * right.z) - (left.z * right.y), (left.z * right.x) - (left.x * right.z),
- (left.x * right.y) - (left.y * right.x)
- );
-}
+#include "d/d_vec.h"
static bool fn_8006A8D0(const mVec2_c &v1, const mVec2_c &v2, const mVec2_c &v3, const mVec2_c &v4, mVec2_c &result) {
mVec2_c t1 = v2 - v1;
@@ -56,7 +47,7 @@ void dSwordSwingEffectProcMgr_c::createSwingEntries(const mVec3_c &v1, const mVe
mVec3_c diff = v1 - v2;
mVec3_c cross_;
- cross(cross_, lastDiff, diff);
+ vecCross(cross_, lastDiff, diff);
f32 diffMag = diff.mag();
@@ -150,7 +141,7 @@ void dSwordSwingEffectProcMgr_c::createSwingEntries(const mVec3_c &v1, const mVe
diff2.normalize();
diff1.normalize();
- cross(cross_, diff1, diff2);
+ vecCross(cross_, diff1, diff2);
cross_.normalize();
// Same code as in dowsing_target...