From 6dd18a9bce55c3423a851ccf0c7fcb7142736ac5 Mon Sep 17 00:00:00 2001 From: robojumper Date: Mon, 29 Dec 2025 18:55:43 +0100 Subject: [PATCH] dAcBlastboss_c::actorExecute OK --- include/d/a/b/d_a_b_lastboss.h | 208 ++++++++++-- include/d/col/c/c_cc_d.h | 13 +- include/d/d_light_env.h | 12 + include/d/d_stage_mgr.h | 2 + include/toBeSorted/d_enemy_sword_mdl.h | 6 + src/REL/d/a/b/d_a_b_lastboss.cpp | 417 +++++++++++++++++++++---- src/d/snd/d_snd_source.cpp | 3 +- 7 files changed, 576 insertions(+), 85 deletions(-) diff --git a/include/d/a/b/d_a_b_lastboss.h b/include/d/a/b/d_a_b_lastboss.h index 7cc03e8f..8f088a58 100644 --- a/include/d/a/b/d_a_b_lastboss.h +++ b/include/d/a/b/d_a_b_lastboss.h @@ -8,6 +8,8 @@ #include "m/m3d/m_anmtexsrt.h" #include "m/m3d/m_mdl.h" #include "m/m3d/m_smdl.h" +#include "m/m_angle.h" +#include "m/m_vec.h" #include "s/s_State.hpp" #include "toBeSorted/d_emitter.h" #include "toBeSorted/d_enemy_sword_mdl.h" @@ -46,6 +48,145 @@ class dAcBlastboss_c : public dAcEnBase_c { /* 0x34 */ dAcBlastboss_c *mpOwner; }; + // BLastBoss.arc > g3d > model.brres > 3DModels(NW4R) > LastBoss > Bones > ... + enum BLastBossModelNode_e { + B_LAST_BOSS_NODE_center = 0, + B_LAST_BOSS_NODE_backbone1 = 1, + B_LAST_BOSS_NODE_backbone2 = 2, + B_LAST_BOSS_NODE_chest = 3, + B_LAST_BOSS_NODE_neck = 4, + B_LAST_BOSS_NODE_head = 5, + B_LAST_BOSS_NODE_browL = 6, + B_LAST_BOSS_NODE_browR = 7, + B_LAST_BOSS_NODE_chin = 8, + B_LAST_BOSS_NODE_hairA1 = 9, + B_LAST_BOSS_NODE_hairA2 = 10, + B_LAST_BOSS_NODE_hairA3 = 11, + B_LAST_BOSS_NODE_hairA4 = 12, + B_LAST_BOSS_NODE_hairBL1 = 13, + B_LAST_BOSS_NODE_hairBL2 = 14, + B_LAST_BOSS_NODE_hairBL3 = 15, + B_LAST_BOSS_NODE_hairBR1 = 16, + B_LAST_BOSS_NODE_hairBR2 = 17, + B_LAST_BOSS_NODE_hairBR3 = 18, + B_LAST_BOSS_NODE_hairC1 = 19, + B_LAST_BOSS_NODE_hairC2 = 20, + B_LAST_BOSS_NODE_hairC3 = 21, + B_LAST_BOSS_NODE_mouthL = 22, + B_LAST_BOSS_NODE_mouthR = 23, + B_LAST_BOSS_NODE_shoulderL = 24, + B_LAST_BOSS_NODE_armL1 = 25, + B_LAST_BOSS_NODE_armL2 = 26, + B_LAST_BOSS_NODE_assistanceL = 27, + B_LAST_BOSS_NODE_wristL = 28, + B_LAST_BOSS_NODE_indexL1 = 29, + B_LAST_BOSS_NODE_indexL2 = 30, + B_LAST_BOSS_NODE_littleL1 = 31, + B_LAST_BOSS_NODE_littleL2 = 32, + B_LAST_BOSS_NODE_middleL1 = 33, + B_LAST_BOSS_NODE_middleL2 = 34, + B_LAST_BOSS_NODE_ringL1 = 35, + B_LAST_BOSS_NODE_ringL2 = 36, + B_LAST_BOSS_NODE_thumbL1 = 37, + B_LAST_BOSS_NODE_thumbL2 = 38, + B_LAST_BOSS_NODE_shoulderR = 39, + B_LAST_BOSS_NODE_armR1 = 40, + B_LAST_BOSS_NODE_armR2 = 41, + B_LAST_BOSS_NODE_assistanceR = 42, + B_LAST_BOSS_NODE_wristR = 43, + B_LAST_BOSS_NODE_indexR1 = 44, + B_LAST_BOSS_NODE_indexR2 = 45, + B_LAST_BOSS_NODE_littleR1 = 46, + B_LAST_BOSS_NODE_littleR2 = 47, + B_LAST_BOSS_NODE_loc_sword01 = 48, + B_LAST_BOSS_NODE_middleR1 = 49, + B_LAST_BOSS_NODE_middleR2 = 50, + B_LAST_BOSS_NODE_ringR1 = 51, + B_LAST_BOSS_NODE_ringR2 = 52, + B_LAST_BOSS_NODE_thumbR1 = 53, + B_LAST_BOSS_NODE_thumbR2 = 54, + B_LAST_BOSS_NODE_belly = 55, + B_LAST_BOSS_NODE_waist = 56, + B_LAST_BOSS_NODE_legL1 = 57, + B_LAST_BOSS_NODE_legL2 = 58, + B_LAST_BOSS_NODE_ankleL = 59, + B_LAST_BOSS_NODE_toeL = 60, + B_LAST_BOSS_NODE_legR1 = 61, + B_LAST_BOSS_NODE_legR2 = 62, + B_LAST_BOSS_NODE_ankleR = 63, + B_LAST_BOSS_NODE_toeR = 64, + B_LAST_BOSS_NODE_skirtA1 = 65, + B_LAST_BOSS_NODE_skirtA2 = 66, + B_LAST_BOSS_NODE_skirtAU1 = 67, + B_LAST_BOSS_NODE_skirtB1 = 68, + B_LAST_BOSS_NODE_skirtB2 = 69, + B_LAST_BOSS_NODE_skirtB3 = 70, + B_LAST_BOSS_NODE_skirtB4 = 71, + B_LAST_BOSS_NODE_skirtB5 = 72, + B_LAST_BOSS_NODE_skirtB6 = 73, + B_LAST_BOSS_NODE_skirtB7 = 74, + B_LAST_BOSS_NODE_skirtB8 = 75, + B_LAST_BOSS_NODE_skirtB9 = 76, + B_LAST_BOSS_NODE_skirtBU1 = 77, + B_LAST_BOSS_NODE_skirtC1 = 78, + B_LAST_BOSS_NODE_skirtC2 = 79, + B_LAST_BOSS_NODE_skirtC3 = 80, + B_LAST_BOSS_NODE_skirtC4 = 81, + B_LAST_BOSS_NODE_skirtC5 = 82, + B_LAST_BOSS_NODE_skirtC6 = 83, + B_LAST_BOSS_NODE_skirtC7 = 84, + B_LAST_BOSS_NODE_skirtC8 = 85, + B_LAST_BOSS_NODE_skirtC9 = 86, + B_LAST_BOSS_NODE_skirtCU1 = 87, + B_LAST_BOSS_NODE_skirtD1 = 88, + B_LAST_BOSS_NODE_skirtD2 = 89, + B_LAST_BOSS_NODE_skirtD3 = 90, + B_LAST_BOSS_NODE_skirtD4 = 91, + B_LAST_BOSS_NODE_skirtD5 = 92, + B_LAST_BOSS_NODE_skirtD6 = 93, + B_LAST_BOSS_NODE_skirtD7 = 94, + B_LAST_BOSS_NODE_skirtD8 = 95, + B_LAST_BOSS_NODE_skirtD9 = 96, + B_LAST_BOSS_NODE_skirtDU1 = 97, + B_LAST_BOSS_NODE_skirtE1 = 98, + B_LAST_BOSS_NODE_skirtE2 = 99, + B_LAST_BOSS_NODE_skirtE3 = 100, + B_LAST_BOSS_NODE_skirtE4 = 101, + B_LAST_BOSS_NODE_skirtE5 = 102, + B_LAST_BOSS_NODE_skirtE6 = 103, + B_LAST_BOSS_NODE_skirtE7 = 104, + B_LAST_BOSS_NODE_skirtE8 = 105, + B_LAST_BOSS_NODE_skirtE9 = 106, + B_LAST_BOSS_NODE_skirtEU1 = 107, + B_LAST_BOSS_NODE_skirtEU2 = 108, + B_LAST_BOSS_NODE_skirtF1 = 109, + B_LAST_BOSS_NODE_skirtF2 = 110, + B_LAST_BOSS_NODE_skirtF3 = 111, + B_LAST_BOSS_NODE_skirtF4 = 112, + B_LAST_BOSS_NODE_skirtF5 = 113, + B_LAST_BOSS_NODE_skirtF6 = 114, + B_LAST_BOSS_NODE_skirtF7 = 115, + B_LAST_BOSS_NODE_skirtF8 = 116, + B_LAST_BOSS_NODE_skirtF9 = 117, + B_LAST_BOSS_NODE_skirtFU1 = 118, + B_LAST_BOSS_NODE_skirtG1 = 119, + B_LAST_BOSS_NODE_skirtG2 = 120, + B_LAST_BOSS_NODE_skirtG3 = 121, + B_LAST_BOSS_NODE_skirtG4 = 122, + B_LAST_BOSS_NODE_skirtG5 = 123, + B_LAST_BOSS_NODE_skirtG6 = 124, + B_LAST_BOSS_NODE_skirtG7 = 125, + B_LAST_BOSS_NODE_skirtG8 = 126, + B_LAST_BOSS_NODE_skirtG9 = 127, + B_LAST_BOSS_NODE_skirtGU1 = 128, + B_LAST_BOSS_NODE_skirtH1 = 129, + B_LAST_BOSS_NODE_skirtH2 = 130, + B_LAST_BOSS_NODE_skirtH3 = 131, + B_LAST_BOSS_NODE_skirtH4 = 132, + B_LAST_BOSS_NODE_skirtH5 = 133, + B_LAST_BOSS_NODE_skirtHU1 = 134, + }; + public: dAcBlastboss_c() : mStateMgr(*this, sStateID::null), mScnCallback(this) {} virtual ~dAcBlastboss_c() {} @@ -75,6 +216,8 @@ private: void fn_143_6720(); void fn_143_A110(s32); void fn_143_7B00(); + void fn_143_7F80(); + void fn_143_9610(); /* 0x0378 */ d3d::AnmMdlWrapper mMdl; /* 0x03E8 */ m3d::anmTexSrt_c mAnmTexSrt; @@ -91,14 +234,19 @@ private: /* 0x0BAC */ STATE_MGR_DECLARE(dAcBlastboss_c); /* 0x0BE8 */ dColliderLinkedList mCcList; /* 0x0BF4 */ dEnemySwordMdl_c mSwordMdl; - /* 0x1130 */ u8 field_0x1130; /* 0x1131 */ u8 field_0x1131; /* 0x1132 */ u8 field_0x1132; /* 0x1133 */ u8 field_0x1133; - - /* 0x1134 */ u8 _0x1134[0x113D - 0x1134]; - + /* 0x1134 */ u8 field_0x1134; + /* 0x1135 */ u8 field_0x1135; + /* 0x1136 */ u8 field_0x1136; + /* 0x1137 */ u8 field_0x1137; + /* 0x1138 */ u8 field_0x1138; + /* 0x1139 */ u8 field_0x1139; + /* 0x113A */ u8 field_0x113A; + /* 0x113B */ u8 field_0x113B; + /* 0x113C */ u8 field_0x113C; /* 0x113D */ u8 field_0x113D; /* 0x113E */ u8 field_0x113E; /* 0x113F */ u8 field_0x113F; @@ -109,28 +257,25 @@ private: /* 0x1144 */ u8 field_0x1144; /* 0x1145 */ u8 field_0x1145; /* 0x1146 */ bool mIsSwordEmpowered; - - /* 0x1147 */ u8 _0x1147[0x114B - 0x1147]; - + /* 0x1147 */ u8 field_0x1147; + /* 0x1148 */ u8 field_0x1148; + /* 0x1149 */ s8 field_0x1149; + /* 0x114A */ u8 field_0x114A; /* 0x114B */ u8 field_0x114B; /* 0x114C */ u8 field_0x114C; /* 0x114D */ u8 field_0x114D; /* 0x114E */ u8 field_0x114E; /* 0x114F */ u8 field_0x114F; + /* 0x1150 */ u8 field_0x1150; - /* 0x1150 */ u8 _0x1150[0x1156 - 0x1150]; + /* 0x1151 */ u8 _0x1151[0x1156 - 0x1151]; + + /* 0x1156 */ u16 field_0x1156[6]; - /* 0x1156 */ u16 field_0x1156; - /* 0x1158 */ u16 field_0x1158; - /* 0x115A */ u16 field_0x115A; - /* 0x115C */ u16 field_0x115C; - /* 0x115E */ u16 field_0x115E; - /* 0x1160 */ u16 field_0x1160; - /* 0x1162 */ u8 _0x1162[0x1164 - 0x1162]; - + /* 0x1164 */ s16 field_0x1164; - + /* 0x1166 */ u8 _0x1166[0x116A - 0x1166]; /* 0x116A */ s16 field_0x116A; @@ -139,8 +284,9 @@ private: /* 0x117C */ s16 field_0x117C; - /* 0x1186 */ u8 _0x117E[0x1186 - 0x117E]; + /* 0x117E */ u8 _0x117E[0x1184 - 0x117E]; + /* 0x1184 */ s16 field_0x1184; /* 0x1186 */ s16 field_0x1186; /* 0x1188 */ u8 _0x1188[0x1190 - 0x1188]; @@ -162,27 +308,32 @@ private: /* 0x11BC */ f32 field_0x11BC; /* 0x11C0 */ f32 field_0x11C0; - /* 0x11C4 */ u8 _0x11C4[0x11D4 - 0x11C4]; + /* 0x11C4 */ u8 _0x11C4[0x11CC - 0x11C4]; + + /* 0x11CC */ f32 field_0x11CC; + + /* 0x11D0 */ u8 _0x11D0[0x11D4 - 0x11D0]; /* 0x11D4 */ s32 field_0x11D4; /* 0x11D8 */ s32 field_0x11D8; - /* 0x11DC */ u8 _0x11DC[0x11E4 - 0x11DC]; - - /* 0x11E4 */ mVec3_c field_0x11E4; - /* 0x11F0 */ mVec3_c field_0x11F0; - /* 0x11FC */ mVec3_c field_0x11FC; + /* 0x11DC */ mAng3_c field_0x11DC; + /* 0x11E4 */ mVec3_c mThumbL2Translation; + /* 0x11F0 */ mVec3_c mBackbone1Translation; + /* 0x11FC */ mVec3_c mChestTranslation; /* 0x1208 */ mVec3_c field_0x1208; - /* 0x1214 */ u8 _0x1214[0x1238 - 0x1214]; + /* 0x1214 */ u8 _0x1214[0x1220 - 0x1214]; - /* 0x1238 */ mVec3_c field_0x1238[2]; + /* 0x1220 */ mVec3_c field_0x1220; + /* 0x122C */ mVec3_c field_0x122C; + /* 0x1238 */ mVec3_c mToeTranslation[2]; /* 0x1250 */ mVec3_c field_0x1250[2]; /* 0x1268 */ UnkLastBossCcSph2 field_0x1260[8]; /* 0x2948 */ UnkLastBossCcSph1 field_0x2948[1]; - /* 0x2B64 */ dEmitter_c mEmitter1; + /* 0x2B64 */ dEmitter_c mWaterEmitter; /* 0x2B98 */ dEmitter_c mEmitter2; /* 0x2BCC */ dEmitter_c mEmitter3; /* 0x2C00 */ dEmitter_c mEmitter4; @@ -191,7 +342,8 @@ private: /* 0x2C9C */ dEmitter_c mEmitter7; /* 0x2CD0 */ LIGHT_INFLUENCE mLightInfo; /* 0x2CEC */ u16 field_0x2CEC; - /* 0x2CEE */ u8 _0x2CEE[0x2D20 - 0x2CEE]; + /* 0x2CEE */ u8 _0x2CEE[0x2D1C - 0x2CEE]; + /* 0x2D1C */ const char *field_0x2D1C; /* 0x2D20 */ dTgSwordBattleGame_c *mpSwordBattleGame; }; diff --git a/include/d/col/c/c_cc_d.h b/include/d/col/c/c_cc_d.h index 7e51421a..69fe1e20 100644 --- a/include/d/col/c/c_cc_d.h +++ b/include/d/col/c/c_cc_d.h @@ -836,6 +836,12 @@ public: void OffAtGrp(u32 grp) { mAt.SetAtFlag(GetAtGrp() & ~grp); } + void SetTgRpm(u32 f) { + mTg.SetRPrm(f); + } + void SetAtRpm(u32 f) { + mAt.SetRPrm(f); + } void SetTgFlag_0xA(u16 flag) { mTg.SetFlag_0xA(flag); @@ -878,7 +884,9 @@ public: return mTg.ChkSet(); } - + void ClrAtActorInfo() { mAt.ClrActorInfo(); } + void ClrTgActorInfo() { mTg.ClrActorInfo(); } + void ClrCoActorInfo() { mCo.ClrActorInfo(); } bool ChkAtEffCounter() { return mAt.ChkEffCounter(); } bool ChkTgEffCounter() { return mTg.ChkEffCounter(); } void ClrAtEffCounter() { mAt.ClrEffCounter(); } @@ -981,6 +989,9 @@ public: void ClrTgElectric() { return mTg.OffSPrm(0x40000); } + void ClrTg_0x10000() { + return mTg.OffSPrm(0x10000); + } u32 ChkTgBonk() const { return mTg.MskSPrm(0x200000); } diff --git a/include/d/d_light_env.h b/include/d/d_light_env.h index 8e4cc20b..0ce649be 100644 --- a/include/d/d_light_env.h +++ b/include/d/d_light_env.h @@ -414,6 +414,10 @@ public: return currentSpf; } + SpfSetting &GetOverrideSpf() { + return mOverrideSpfSetting; + } + const PaletteEAF_smol_entry &getSmallEAF(s32 idx1, s32 idx2) { return field_0x38E4.field_0x00[idx1].field_0x00[idx2]; } @@ -430,6 +434,14 @@ public: return field_0x2F1C; } + u32 getField_0x38DC() const { + return field_0x38DC; + } + + void setField_0x38DC(u32 v) { + field_0x38DC = v; + } + private: /* 0x0004 */ Spf currentSpf; /* 0x020C */ Spf spfs[20]; diff --git a/include/d/d_stage_mgr.h b/include/d/d_stage_mgr.h index de4d0b47..65293fcc 100644 --- a/include/d/d_stage_mgr.h +++ b/include/d/d_stage_mgr.h @@ -169,6 +169,8 @@ public: nw4r::g3d::Camera getCamera(s32 idx); + void fn_80199B60(u8); + dFader_c *getFader() { return &mFader; } diff --git a/include/toBeSorted/d_enemy_sword_mdl.h b/include/toBeSorted/d_enemy_sword_mdl.h index 33527979..96989e51 100644 --- a/include/toBeSorted/d_enemy_sword_mdl.h +++ b/include/toBeSorted/d_enemy_sword_mdl.h @@ -8,6 +8,7 @@ #include "egg/gfx/eggTexture.h" #include "m/m3d/m_smdl.h" #include "m/m_allocator.h" +#include "m/m_angle.h" #include "m/m_mtx.h" #include "m/m_quat.h" #include "m/m_vec.h" @@ -45,6 +46,11 @@ public: ); void calc(const mMtx_c &mtx, const mVec3_c &v1, bool mass); + void calc(const mMtx_c &mtx, mAng angle, bool mass) { + // A bit of a wild inline but this vector is very low on the dAcBlastboss_c::actorExecute stack + mVec3_c v1 = mVec3_c(angle.sin(), 0.0f, angle.cos()); + calc(mtx, v1, mass); + } bool entry(dAcObjBase_c *obj, dShadowCircle_c *shadow, mQuat_c *quat); void fn_8006B640(); diff --git a/src/REL/d/a/b/d_a_b_lastboss.cpp b/src/REL/d/a/b/d_a_b_lastboss.cpp index f19e8390..6d4858b7 100644 --- a/src/REL/d/a/b/d_a_b_lastboss.cpp +++ b/src/REL/d/a/b/d_a_b_lastboss.cpp @@ -5,15 +5,21 @@ #include "common.h" #include "d/a/d_a_player.h" #include "d/a/obj/d_a_obj_base.h" +#include "d/col/cc/d_cc_s.h" #include "d/d_base.h" #include "d/d_light_env.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/flag/sceneflag_manager.h" #include "d/snd/d_snd_wzsound.h" #include "d/t/d_t_sword_battle_game.h" #include "f/f_base.h" #include "f/f_manager.h" #include "f/f_profile_name.h" #include "m/m3d/m_fanm.h" +#include "m/m_angle.h" #include "m/m_mtx.h" #include "m/m_vec.h" #include "nw4r/g3d/res/g3d_resfile.h" @@ -205,7 +211,7 @@ int dAcBlastboss_c::create() { field_0x11D4 = field_0x11D8 = -1; - mEmitter1.init(this); + mWaterEmitter.init(this); mEmitter2.init(this); // mEmitter3.init(this); // TODO why not this one... mEmitter4.init(this); @@ -226,6 +232,9 @@ int dAcBlastboss_c::create() { return SUCCEEDED; } +// TODO +extern "C" const s16 notsure[] = {0xA000, 0xC000, 0xE000, 0xF000, 0x0000, 0x1000, 0x2000, 0x4000}; + int dAcBlastboss_c::doDelete() { dLightEnv_c::GetPInstance()->plight_cut(&mLightInfo); return SUCCEEDED; @@ -245,33 +254,15 @@ int dAcBlastboss_c::actorExecute() { field_0x1131 = 0; field_0x1141 = 0; field_0x114E = 0; - + field_0x11A4 = 0.0f; mLightInfo.mScale = 0.0f; field_0x11B0 = 0.7f; - if (field_0x1156 != 0) { - field_0x1156--; - } - - if (field_0x1158 != 0) { - field_0x1158--; - } - - if (field_0x115A != 0) { - field_0x115A--; - } - - if (field_0x115C != 0) { - field_0x115C--; - } - - if (field_0x115E != 0) { - field_0x115E--; - } - - if (field_0x1160 != 0) { - field_0x1160--; + for (int i = 0; i < 6; i++) { + if (field_0x1156[i] != 0) { + field_0x1156[i]--; + } } if (mMdlCallback.field_0x04 != 0) { @@ -294,16 +285,14 @@ int dAcBlastboss_c::actorExecute() { field_0x113E--; } + mVec3_c vEff; mVec3_c linkPos = link->getPosition(); field_0x116A = cLib::targetAngleY(mPosition, linkPos); - // TODO maybe inline - mVec3_c posDiff = link->getPosition() - mPosition; - field_0x1190 = posDiff.absXZ(); - + field_0x1190 = link->getPosition().absXZTo(mPosition); field_0x1186 = field_0x116A - mRotation.y; mSwordMdl.setAttackActive(false); - + mCc4.ClrAtSet(); mCc5.ClrAtSet(); @@ -312,9 +301,9 @@ int dAcBlastboss_c::actorExecute() { mStateMgr.executeState(); } - mRotation.x = mRotationCopy.x; - mRotation.z = mRotationCopy.z; - sLib::addCalcAngle(&mRotation.y.mVal, mRotationCopy.y, 2, 0x800); + mRotation.x = mAngle.x; + mRotation.z = mAngle.z; + sLib::addCalcAngle(&mRotation.y.mVal, mAngle.y, 2, 0x800); mMdl.play(); if (!field_0x114F) { @@ -350,7 +339,7 @@ int dAcBlastboss_c::actorExecute() { mScale.set(0.95f, 0.95f, 0.95f); mMdl.getModel().setScale(mScale); mMdl.getModel().setLocalMtx(mWorldMtx); - if (!field_0x114F) { + if (!field_0x1141) { mAnmTexSrt.play(); } @@ -359,15 +348,15 @@ int dAcBlastboss_c::actorExecute() { nw4r::g3d::ResMdl resMdl = mMdl.getModel().getResMdl(); mMtx_c nodeMtx; mMdl.getModel().getNodeWorldMtx(resMdl.GetResNode("loc_sword01").GetID(), nodeMtx); + mMtx_c rotMtx; mMtx_c scaleMtx; scaleMtx.scaleS(1.05f, 1.05f, 1.05f); MTXConcat(nodeMtx, scaleMtx, nodeMtx); - // TODO - inline? - mVec3_c v(mRotation.y.sin(), 0.0f, mRotation.y.cos()); - mSwordMdl.calc(nodeMtx, v, false); + mSwordMdl.calc(nodeMtx, mRotation.y, false); - mVec3_c vEff(0.0f, -120.0f, 0.0f); + vEff.set(0.0f, -120.0f, 0.0f); + // TODO number if ((s32)field_0x1144 == 9) { vEff.y = -80.0f; if (field_0x1190 > 300.0f) { @@ -415,40 +404,360 @@ int dAcBlastboss_c::actorExecute() { field_0x114B = 0; } - // TODO NODE IDs - mMdl.getModel().getNodeWorldMtx(0x26, nodeMtx); - nodeMtx.getTranslation(field_0x11E4); - mMdl.getModel().getNodeWorldMtx(1, nodeMtx); - nodeMtx.getTranslation(field_0x11F0); - mMdl.getModel().getNodeWorldMtx(3, nodeMtx); - nodeMtx.getTranslation(field_0x11FC); - mMdl.getModel().getNodeWorldMtx(0x3C, nodeMtx); - nodeMtx.getTranslation(field_0x1238[0]); - mMdl.getModel().getNodeWorldMtx(0x40, nodeMtx); - nodeMtx.getTranslation(field_0x1238[1]); + mMdl.getModel().getNodeWorldMtx(B_LAST_BOSS_NODE_thumbL2, nodeMtx); + nodeMtx.getTranslation(mThumbL2Translation); + mMdl.getModel().getNodeWorldMtx(B_LAST_BOSS_NODE_backbone1, nodeMtx); + nodeMtx.getTranslation(mBackbone1Translation); + mMdl.getModel().getNodeWorldMtx(B_LAST_BOSS_NODE_chest, nodeMtx); + nodeMtx.getTranslation(mChestTranslation); + mMdl.getModel().getNodeWorldMtx(B_LAST_BOSS_NODE_toeL, nodeMtx); + nodeMtx.getTranslation(mToeTranslation[0]); + mMdl.getModel().getNodeWorldMtx(B_LAST_BOSS_NODE_toeR, nodeMtx); + nodeMtx.getTranslation(mToeTranslation[1]); - mMdl.getModel().getNodeWorldMtx(5, nodeMtx); + mMdl.getModel().getNodeWorldMtx(B_LAST_BOSS_NODE_head, nodeMtx); mVec3_c tmp1(0.0f, 0.0f, 0.0f); MTXMultVec(nodeMtx, tmp1, mPositionCopy2); - // TODO - mPositionCopy3 = mVec3_c(mPositionCopy2.x, mPositionCopy2.y + 50.0f, mPositionCopy2.z); + mVec3_c v3; + v3.x = mPositionCopy2.x; + v3.y = mPositionCopy2.y + 50.0f; + v3.z = mPositionCopy2.z; + mPositionCopy3 = v3; if (field_0x1132) { fn_80030c20(0, 1500.0f, 50.0f, -200.0f, 200.0f); } nodeMtx.YrotS(mRotation.y); + mVec3_c tmpCc; - if (link->isAttacking() && *mStateMgr.getStateID() == StateID_Guard) { - if (field_0x1144 == 9) { + if (link->isAttacking() && mStateMgr.isState(StateID_Guard)) { + // TODO number + if ((s32)field_0x1144 == 9) { + tmpCc.x = 0.0f; + tmpCc.y = 0.0f; tmpCc.z = 100.0f; - // TODO - ... + if (field_0x1190 > 300.0f) { + tmpCc.z = (field_0x1190 - 300.0f) + 100.0f; + if (tmpCc.z > 300) { + tmpCc.z = 300.0f; + } + } + } else { + tmpCc.x = 0.0f; + tmpCc.y = 0.0f; + tmpCc.z = 130.0f; } + mCc1.SetR(20.0f); + } else if (mStateMgr.isState(StateID_ThunderWait)) { + tmpCc.set(0.0f, 0.0f, 0.0f); + mCc1.SetR(150.0f); + } else { + tmpCc.set(0.0f, 0.0f, 80.0f); + mCc1.SetR(55.0f); } MTXMultVec(nodeMtx, tmpCc, tmpCc); tmpCc += mPosition; + if (link->isAttacking() && field_0x1190 < 400.0f) { + tmpCc.y += 100.0f; + mCc1.SetH(100.0f); + } else { + mCc1.SetH(250.0f); + } + mCc1.SetC(tmpCc); + + // TODO - ... + tmpCc.x = mChestTranslation.x; + tmpCc.y = mChestTranslation.y; + tmpCc.z = mChestTranslation.z; + tmpCc.y = mPosition.y; + + if (!field_0x1141) { + mCc3.SetR(100.0f); + } else { + mCc3.SetR(200.0f); + } + mCc3.SetC(tmpCc); + + tmpCc.x = mPosition.x; + tmpCc.y = mPosition.y + 150.0f; + tmpCc.z = mPosition.z; + + mCc2.SetC(tmpCc); + + // TODO + field_0x1250[0] = mToeTranslation[0] + (mToeTranslation[1] - mToeTranslation[0]) * 0.5f; + // UB: this should use string comparison functions for robustness, but + // probably works fine in MWCC + if ((field_0x2D1C == "CatchThunderEnd" || field_0x2D1C == "Stan") && mMdl.getAnm().getFrame() <= 3.0f) { + field_0x11A4 = 25.0f; + } + + fn_143_7F80(); + + if (!link->isAttacking()) { + field_0x1143 = 1; + } + + if (field_0x1143 == 0) { + mCc1.SetTg_0x4B(1); + // TODO + mCc1.mTg.field_0x6C = field_0x1208; + } else { + field_0x1143--; + tmpCc.set(0.0f, -10000.0f, 0.0); + mCc1.SetTg_0x4B(1); + // TODO + mCc1.mTg.field_0x6C = tmpCc; + } + + mCc1.ClrTg_0x10000(); + + if (field_0x1142 != 0) { + field_0x1142--; + mCcList.ClrTg(); + } else { + mCcList.TgSet(); + } + mCcList.registerColliders(); + + if (field_0x1139 != 0) { + mCc4.OnAtSet(); + if (field_0x1139 == 1) { + mCc4.setCenter(mThumbL2Translation); + field_0x1139 = 2; + } else { + mCc4.moveCenter(mThumbL2Translation); + } + dCcS::GetInstance()->Set(&mCc4); + } + + static mAng3_c sEffRot(0, 0, 0); + static mVec3_c sEffScale(1.5f, 1.5f, 1.5f); + mVec3_c effPos(mPosition.x, 10.0f, mPosition.z); + // Basically the same code as in dWaterEffect_c::execute + mWaterEmitter.holdEffect(PARTICLE_RESOURCE_ID_MAPPING_127_, effPos, &sEffRot, &sEffScale, nullptr, nullptr); + f32 rate = nw4r::math::FAbs(mSpeed) * 0.02f; + rate = rate > 0.95f ? 0.95f : rate; + mWaterEmitter.setRate(rate + 0.05f); + + bool footSplash[2] = {false, false}; + // UB: this should use string comparison functions for robustness, but + // probably works fine in MWCC + if (field_0x2D1C == "Walk" || field_0x2D1C == "WalkBt") { + if (mMdl.getAnm().checkFrame(22.0f)) { + footSplash[0] = true; + } else if (mMdl.getAnm().checkFrame(48.0f)) { + footSplash[1] = true; + } + } else if (field_0x2D1C == "TurnR") { + if (mMdl.getAnm().checkFrame(31.0f)) { + footSplash[0] = true; + } else if (mMdl.getAnm().checkFrame(19.0f)) { + footSplash[1] = true; + } + } else if (field_0x2D1C == "TurnL") { + if (mMdl.getAnm().checkFrame(31.0f)) { + footSplash[1] = true; + } else if (mMdl.getAnm().checkFrame(19.0f)) { + footSplash[0] = true; + } + } else if (field_0x2D1C == "AttackBreak") { + if (mMdl.getAnm().checkFrame(16.0f)) { + footSplash[0] = true; + } + } else if (field_0x2D1C == "AttackL") { + if (mMdl.getAnm().checkFrame(26.0f)) { + footSplash[1] = true; + } + } else if (field_0x2D1C == "AttackR") { + if (mMdl.getAnm().checkFrame(24.0f)) { + footSplash[1] = true; + } + } else if (field_0x2D1C == "AttackU") { + if (mMdl.getAnm().checkFrame(10.0f)) { + footSplash[1] = true; + } else if (mMdl.getAnm().checkFrame(24.0f)) { + footSplash[0] = true; + } + } else if (field_0x2D1C == "Counter") { + if (mMdl.getAnm().checkFrame(21.0f)) { + footSplash[0] = true; + } else if (mMdl.getAnm().checkFrame(45.0f)) { + footSplash[1] = true; + } + } else if (field_0x2D1C == "AttackJumpEnd") { + if (mMdl.getAnm().checkFrame(6.0f)) { + footSplash[1] = true; + } + } else if (field_0x2D1C == "DownGetUp") { + if (mMdl.getAnm().checkFrame(137.0f)) { + footSplash[1] = true; + } + } else if (field_0x2D1C == "DownEscapeL") { + if (mMdl.getAnm().checkFrame(15.0f)) { + footSplash[0] = true; + } else if (mMdl.getAnm().checkFrame(17.0f)) { + footSplash[1] = true; + } + } else if (field_0x2D1C == "DownEscapeR") { + if (mMdl.getAnm().checkFrame(15.0f)) { + footSplash[1] = true; + } else if (mMdl.getAnm().checkFrame(17.0f)) { + footSplash[0] = true; + } + } else if (field_0x2D1C == "ThunderDemo") { + if (mMdl.getAnm().checkFrame(18.0f)) { + footSplash[1] = true; + } + } else if (field_0x2D1C == "AttackThunder") { + if (mMdl.getAnm().checkFrame(25.0f)) { + footSplash[0] = true; + } + } + + // Spawn splash effects + for (int i = 0; i < 2; i++) { + if (footSplash[i]) { + mToeTranslation[i].y = 10.0f; + dJEffManager_c::spawnEffect( + PARTICLE_RESOURCE_ID_MAPPING_855_, mToeTranslation[i], nullptr, nullptr, nullptr, nullptr, 0, 0 + ); + } + } + + if (field_0x1149 != 0) { + if (!link->checkSwordAndMoreStates(0x400000) && (field_0x1149 < 0 || !mIsSwordEmpowered)) { + if (field_0x1184 == 0) { + if (dLightEnv_c::GetPInstance()->getField_0x38DC() == 0) { + dLightEnv_c::GetPInstance()->setField_0x38DC(1); + fn_143_A110(100); + } + } else if (!mIsSwordEmpowered || (dScGame_c::getUpdateFrameCount() & 0b11) == 0) { + field_0x1184--; + } + } else { + fn_143_A110(100); + } + sLib::addCalcScaledDiff(&field_0x11CC, 1.0f, 1.0f, 0.1f); + } + + // TODO: inline doesn't work :( + dLightEnv_c::GetInstance().GetOverrideSpf().mIdxStart = 1; + dLightEnv_c::GetInstance().GetOverrideSpf().mIdxEnd = 2; + dLightEnv_c::GetInstance().GetOverrideSpf().mRatio = field_0x11CC; + + if (field_0x1147 && field_0x1148 != 0) { + field_0x1148--; + field_0x1220 += field_0x122C; + nodeMtx.transS(field_0x1220); + nodeMtx.ZXYrotM(field_0x11DC); + + if (!field_0x1150) { + if (mCc5.ChkAtHit() || mCc5.ChkTgHit()) { + dJEffManager_c::spawnEffect(PARTICLE_RESOURCE_ID_MAPPING_850_, nodeMtx, nullptr, nullptr, 0, 0); + if (mCc5.ChkTgHit() && mCc5.ChkTgAtHitType(AT_TYPE_BUGNET)) { + getSoundSource()->startSoundAtPosition2(SE_BLasBos_EmitThunderBeam, field_0x1220); + field_0x1148 = 0x3C; + field_0x122C *= -1.0f; + dRumble_c::start(dRumble_c::sRumblePreset2, dRumble_c::FLAG_SLOT0); + dStageMgr_c::GetInstance()->fn_80199B60(3); + field_0x1150 = 1; + } else { + field_0x1147 = 0; + mMtx_c mtx; + mtx.transS(0.0f, -100000.0f, 0.0f); + MTXConcat(nodeMtx, mtx, nodeMtx); + getSoundSource()->startSoundAtPosition2(SE_BLasBos_BeamCrossCrush, field_0x1220); + } + mCc5.SetTgRpm(0); + mCc5.ClrTgActorInfo(); + mCc5.SubtractTgEffCounter(); + mCc5.SetAtRpm(0); + mCc5.ClrAtActorInfo(); + mCc5.SubtractAtEffCounter(); + } + } else { + if ((field_0x1220 - mPosition).absXZ() < 150.0f) { + dJEffManager_c::spawnEffect(PARTICLE_RESOURCE_ID_MAPPING_850_, nodeMtx, nullptr, nullptr, 0, 0); + field_0x1147 = false; + mMtx_c mtx; + mtx.transS(0.0f, -100000.0f, 0.0f); + MTXConcat(nodeMtx, mtx, nodeMtx); + getSoundSource()->startSoundAtPosition2(SE_BLasBos_BeamCrossCrush, field_0x1220); + v3.set(0.0f, 0.0f, 20.0f); + rotMtx.YrotS(link->mRotation.y); + MTXMultVec(rotMtx, v3, v3); + field_0x119C = v3.x; + field_0x11A0 = v3.z; + mStateMgr.changeState(StateID_Stun); + } + } + mLightInfo.mPos = field_0x1220; + if ((dScGame_c::getUpdateFrameCount() & 2) != 0) { + mLightInfo.SetScale(300.0f); + } else { + mLightInfo.SetScale(200.0f); + } + + if (field_0x1148 <= 10) { + // TODO: lightning timer? + if (field_0x1148 == 10) { + mEmitter5.setFading(10); + } + if (field_0x1148 == 0) { + field_0x1147 = 0; + } + mCc5.ClrAtSet(); + } else { + if (!field_0x1150) { + mCc5.OnAtSet(); + mCc5.SetR(100.0f); + mCc5.moveCenter(field_0x1220); + dCcS::GetInstance()->Set(&mCc5); + } + getSoundSource()->holdSoundAtPosition(SE_BLasBos_ThunderBeamFly, field_0x1220); + } + mEmitter5.holdEffect(PARTICLE_RESOURCE_ID_MAPPING_618_, nodeMtx, nullptr, nullptr); + } + + if (field_0x114A != 0) { + field_0x114A--; + mCc5.OnAtSet(); + mCc5.SetC(mPosition); + mCc5.SetR(300.0f - field_0x114A * 30.0f); + mCc5.SetAtVec(link->getPosition() - mPosition); + dCcS::GetInstance()->Set(&mCc5); + if (field_0x114A == 8) { + vEff.x = mPosition.x; + vEff.y = 10.0f; + vEff.z = mPosition.z; + dJEffManager_c::spawnEffect( + PARTICLE_RESOURCE_ID_MAPPING_842_, vEff, nullptr, nullptr, nullptr, nullptr, 0, 0 + ); + } + } + fn_143_9610(); + + SceneflagManager *mgr = SceneflagManager::sInstance; + if (mgr != nullptr) { + if (mStateMgr.isState(StateID_ThunderWait)) { + mgr->setFlag(getRoomId(), field_0x1130); + } else { + mgr->unsetFlag(getRoomId(), field_0x1130); + } + } + + if (field_0x1149) { + // "Target lock: Demise" (Phase 2) + mTargetFiTextID = 0x38; + } else { + // "Target lock: Demise" (Phase 1) + mTargetFiTextID = 0x37; + } + return SUCCEEDED; } diff --git a/src/d/snd/d_snd_source.cpp b/src/d/snd/d_snd_source.cpp index f71dfb3a..00ddbbee 100644 --- a/src/d/snd/d_snd_source.cpp +++ b/src/d/snd/d_snd_source.cpp @@ -472,8 +472,7 @@ bool dSoundSource_c::startBgHitSound( return startBgHitSound(soundLabelToSoundId(label), polyAttr0, polyAttr1, position); } -// exact copy of startSoundAtPosition - used only for when the hookshot -// hits the water level +// exact copy of startSoundAtPosition bool dSoundSource_c::startSoundAtPosition2(u32 soundId, const nw4r::math::VEC3 *position) { if (!d_s_vt_0x1AC(soundId)) { return false;