From 4543ec129ec02649b24ae0e20d8325a5f066c9b1 Mon Sep 17 00:00:00 2001 From: robojumper Date: Wed, 16 Oct 2024 16:24:02 +0200 Subject: [PATCH] d_t_reaction, angle chaos edition (#56) * d_t_reaction, angle chaos edition * Fix * prettier params * fixup --------- Co-authored-by: elijah-thomas774 --- config/SOUE01/rels/d_t_reactionNP/splits.txt | 3 + config/SOUE01/rels/d_t_reactionNP/symbols.txt | 25 +- config/SOUE01/symbols.txt | 4 +- include/d/a/obj/d_a_obj_base.h | 2 +- include/d/a/obj/d_a_obj_item.h | 8 +- include/d/col/cc/d_cc_d.h | 35 ++- include/d/t/d_t_reaction.h | 59 +++- include/m/m_angle.h | 8 + src/REL/d/a/obj/d_a_obj_spike.cpp | 2 +- src/REL/d/a/obj/d_a_obj_toD3_stone_figure.cpp | 2 +- src/REL/d/a/obj/d_a_obj_triforce.cpp | 2 +- src/REL/d/t/d_t_reaction.cpp | 295 +++++++++++++++++- src/d/col/cc/d_cc_d.cpp | 4 + 13 files changed, 423 insertions(+), 26 deletions(-) diff --git a/config/SOUE01/rels/d_t_reactionNP/splits.txt b/config/SOUE01/rels/d_t_reactionNP/splits.txt index 7ea3c410..f8f254c2 100644 --- a/config/SOUE01/rels/d_t_reactionNP/splits.txt +++ b/config/SOUE01/rels/d_t_reactionNP/splits.txt @@ -17,3 +17,6 @@ REL/global_destructor_chain.c: REL/d/t/d_t_reaction.cpp: .text start:0x000000F0 end:0x00001558 .ctors start:0x00000000 end:0x00000004 + .rodata start:0x00000000 end:0x00000028 + .data start:0x00000000 end:0x000001EC + .bss start:0x00000008 end:0x00000048 diff --git a/config/SOUE01/rels/d_t_reactionNP/symbols.txt b/config/SOUE01/rels/d_t_reactionNP/symbols.txt index b5b7ed28..626c688f 100644 --- a/config/SOUE01/rels/d_t_reactionNP/symbols.txt +++ b/config/SOUE01/rels/d_t_reactionNP/symbols.txt @@ -8,24 +8,23 @@ __dt__26sFState_c<13dTgReaction_c>Fv = .text:0x000001D0; // type:function size:0 __dt__29sFStateFct_c<13dTgReaction_c>Fv = .text:0x00000230; // type:function size:0x6C __dt__82sStateMgr_c<13dTgReaction_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>Fv = .text:0x000002A0; // type:function size:0xA0 __dt__52sFStateMgr_c<13dTgReaction_c,20sStateMethodUsr_FI_c>Fv = .text:0x00000340; // type:function size:0xA4 -fn_578_3F0 = .text:0x000003F0; // type:function size:0x8 -TgReaction__init = .text:0x00000400; // type:function size:0x350 +createHeap__13dTgReaction_cFv = .text:0x000003F0; // type:function size:0x8 +create__13dTgReaction_cFv = .text:0x00000400; // type:function size:0x350 changeState__82sStateMgr_c<13dTgReaction_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>FRC12sStateIDIf_c = .text:0x00000750; // type:function size:0x10 -fn_578_760 = .text:0x00000760; // type:function size:0x24 -TgReaction__update = .text:0x00000790; // type:function size:0x84 +doDelete__13dTgReaction_cFv = .text:0x00000760; // type:function size:0x24 +actorExecute__13dTgReaction_cFv = .text:0x00000790; // type:function size:0x84 executeState__82sStateMgr_c<13dTgReaction_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>Fv = .text:0x00000820; // type:function size:0x10 -fn_578_830 = .text:0x00000830; // type:function size:0x8 +draw__13dTgReaction_cFv = .text:0x00000830; // type:function size:0x8 initializeState_Wait__13dTgReaction_cFv = .text:0x00000840; // type:function size:0x4 -executeState_Wait__13dTgReaction_cFv = .text:0x00000850; // type:function size:0x40 -fn_578_890 = .text:0x00000890; // type:function size:0x4 +executeState_Wait__13dTgReaction_cFv = .text:0x00000850; // type:function size:0x44 finalizeState_Wait__13dTgReaction_cFv = .text:0x000008A0; // type:function size:0x4 -TgReaction__bonkGiveItemMaybe = .text:0x000008B0; // type:function size:0x2B8 -fn_578_B70 = .text:0x00000B70; // type:function size:0xE0 -TgReaction__sling/BellowsGiveItemMaybe = .text:0x00000C50; // type:function size:0x108 -TgReaction__unregisterDowsingTarget = .text:0x00000D60; // type:function size:0x44 +checkForBonkItem__13dTgReaction_cFv = .text:0x000008B0; // type:function size:0x2B8 +checkForBubble__13dTgReaction_cFv = .text:0x00000B70; // type:function size:0xE0 +checkForSlingBellowsItem__13dTgReaction_cFv = .text:0x00000C50; // type:function size:0x108 +onDelete__13dTgReaction_cFv = .text:0x00000D60; // type:function size:0x44 fn_578_DB0 = .text:0x00000DB0; // type:function size:0xB4 -fn_578_E70 = .text:0x00000E70; // type:function size:0x184 -fn_578_1000 = .text:0x00001000; // type:function size:0xA4 +spawnHearts__13dTgReaction_cFlRC7mVec3_cl4mAng = .text:0x00000E70; // type:function size:0x184 +rndRange<4mAng>__F4mAng4mAng_4mAng = .text:0x00001000; // type:function size:0xA4 __dt__13dTgReaction_cFv = .text:0x000010B0; // type:function size:0xD8 getStateID__82sStateMgr_c<13dTgReaction_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>CFv = .text:0x00001190; // type:function size:0x10 build__29sFStateFct_c<13dTgReaction_c>FRC12sStateIDIf_c = .text:0x000011A0; // type:function size:0x60 diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 062fe9fc..09fdd4c4 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -1118,7 +1118,7 @@ postExecute__12dAcObjBase_cFQ27fBase_c12MAIN_STATE_e = .text:0x8002E2A0; // type preDraw__12dAcObjBase_cFv = .text:0x8002E330; // type:function size:0x27C getObjectListEntry__12dAcObjBase_cFv = .text:0x8002E5B0; // type:function size:0x8 restorePosRotFromCopy__12dAcObjBase_cFv = .text:0x8002E5C0; // type:function size:0x70 -create__12dAcObjBase_cFQ28fProfile14PROFILE_NAME_eScUlP7mVec3_cP7mAng3_cP7mVec3_cUl = .text:0x8002E630; // type:function size:0x98 +create__12dAcObjBase_cFQ28fProfile14PROFILE_NAME_eUlUlP7mVec3_cP7mAng3_cP7mVec3_cUl = .text:0x8002E630; // type:function size:0x98 create__12dAcObjBase_cFPcUlUlP7mVec3_cP7mAng3_cP7mVec3_cUlUsSc = .text:0x8002E6D0; // type:function size:0xA0 ActorObjectBase__findObject = .text:0x8002E770; // type:function size:0x7C getNextActorInList = .text:0x8002E7F0; // type:function size:0x58 @@ -18787,7 +18787,7 @@ fn_80328DA0 = .text:0x80328DA0; // type:function size:0xC fn_80328DB0 = .text:0x80328DB0; // type:function size:0xC fn_80328DC0 = .text:0x80328DC0; // type:function size:0xC GetAtActor__12dCcD_GObjInfFv = .text:0x80328DD0; // type:function size:0x4 -UnkCollider__checkCollidedMask = .text:0x80328DE0; // type:function size:0x18 +CheckCollidedMask__12dCcD_GObjInfFUl = .text:0x80328DE0; // type:function size:0x18 ActorEnemyBase__getRoomIdCopy = .text:0x80328E00; // type:function size:0x8 fn_80328E10 = .text:0x80328E10; // type:function size:0xC UnkCollider__getDamage = .text:0x80328E20; // type:function size:0x8 diff --git a/include/d/a/obj/d_a_obj_base.h b/include/d/a/obj/d_a_obj_base.h index 857bcd09..e562a392 100644 --- a/include/d/a/obj/d_a_obj_base.h +++ b/include/d/a/obj/d_a_obj_base.h @@ -111,7 +111,7 @@ public: public: /* 8002e630 */ static dAcObjBase_c *create( - fProfile::PROFILE_NAME_e actorId, s8 roomId, u32 params1, mVec3_c *pos, mAng3_c *rot, mVec3_c *scale, + fProfile::PROFILE_NAME_e actorId, u32 roomId, u32 params1, mVec3_c *pos, mAng3_c *rot, mVec3_c *scale, u32 params2 ); /* 8002e6d0 */ static dAcObjBase_c *create( diff --git a/include/d/a/obj/d_a_obj_item.h b/include/d/a/obj/d_a_obj_item.h index a07fad3b..4a2cf494 100644 --- a/include/d/a/obj/d_a_obj_item.h +++ b/include/d/a/obj/d_a_obj_item.h @@ -6,6 +6,12 @@ // Ghidra: AcItem // Size: 0xd68 // official name -class dAcItem_c : public dAcObjBase_c {}; +class dAcItem_c : public dAcObjBase_c { +public: + static u32 createItemParams(u16 itemId, u32 subType, u32 unk, u8 unk2, u8, u8); + + static void spawnItem(u16 item, u32 room, const mVec3_c &pos, const mAng3_c &rot, u32 params, u32 arg); + static void spawnDrop(u16 item, u32 room, const mVec3_c &pos, const mAng3_c &rot); +}; #endif diff --git a/include/d/col/cc/d_cc_d.h b/include/d/col/cc/d_cc_d.h index f5a3664f..0df7adde 100644 --- a/include/d/col/cc/d_cc_d.h +++ b/include/d/col/cc/d_cc_d.h @@ -69,6 +69,9 @@ public: void resetField0x14() { field_0x14 = 0; } + u32 getField0x14() { + return field_0x14; + } void decreaseCount(); void unlink(); dAcBase_c *getActor(); @@ -94,7 +97,8 @@ struct dCcD_SrcGObjAt { struct dCcD_SrcGObjTg { /* 0x00 */ dCcD_SrcGAtTgCoCommonBase base; /* 0x04 */ u32 field_0x04; - /* 0x08 */ u32 field_0x08; + /* 0x08 */ u16 field_0x08; + /* 0x10 */ u16 field_0x0A; /* 0x0C */ u16 field_0x0C; /* 0x0E */ u16 field_0x0E; }; @@ -151,7 +155,8 @@ private: /* 0x4C */ u32 field_0x4C; /* 0x50 */ u32 field_0x50; /* 0x54 */ u32 field_0x54; - /* 0x58 */ u8 field_0x58[0x6C - 0x58]; + /* 0x58 */ u32 field_0x58; + /* 0x5C */ u8 field_0x5C[0x6C - 0x5C]; /* 0x6C */ mVec3_c field_0x6C; /* 0x78 */ u32 field_0x78; @@ -167,6 +172,15 @@ public: void set0x4C(u32 val) { field_0x4C = val; } + void setSrcFlag(u32 flag) { + mSrc.base.mGFlag = flag; + } + void setSrc0x0A(u32 flag) { + mSrc.field_0x0A = flag; + } + u32 get0x58() { + return field_0x58; + } void init(const dCcD_SrcGObjTg *); void adjustHitPos(f32 dx, f32 dz); }; @@ -250,6 +264,10 @@ struct UnkCCDStruct { void setField0x38ToMagicValue() { field_0x38 = 0xD; } + + void setField0x38(s32 val) { + field_0x38 = val; + } }; // Object Info @@ -292,10 +310,22 @@ public: mGObjAt.SetSomeVec(p); } + inline void setTgFlag(u32 flag) { + mGObjTg.setSrcFlag(flag); + } + inline mVec3_c *getAtVec() { return mGObjAt.GetSomeVec(); } + bool someInteractCheck() { + return ((mGObjTg.getField0x14() & 1) != 0 && mGObjTg.getActor() != nullptr); + } + + void setTgField0x0A(u32 val) { + mGObjTg.setSrc0x0A(val); + } + void ResetAtHit(); void ResetTgHit(); void ResetCoHit(); @@ -304,6 +334,7 @@ public: mVec3_c *GetAtHitPosP2(); dAcBase_c *GetAtActor(); + bool CheckCollidedMask(u32 mask); dAcBase_c *GetTgActor(); dAcBase_c *GetCoActor(); diff --git a/include/d/t/d_t_reaction.h b/include/d/t/d_t_reaction.h index c716c7ab..43fbca63 100644 --- a/include/d/t/d_t_reaction.h +++ b/include/d/t/d_t_reaction.h @@ -2,18 +2,73 @@ #define D_T_REACTION_H #include +#include #include #include +#include class dTgReaction_c : public dAcObjBase_c { public: - dTgReaction_c() : mStateMgr(*this, sStateID::null) {} + dTgReaction_c() : mStateMgr(*this, sStateID::null), mDowsingTarget(this, DowsingTarget::SLOT_NONE) {} virtual ~dTgReaction_c() {} + virtual bool createHeap() override; + virtual int create() override; + virtual int actorExecute() override; + virtual int draw() override; + virtual int doDelete() override; STATE_FUNC_DECLARE(dTgReaction_c, Wait); private: - /* 0x??? */ STATE_MGR_DECLARE(dTgReaction_c); + static dCcD_SrcCyl sCcSrc; + static const f32 sRadius; + static const f32 sHeight; + + enum ReactType { + REACT_BONK, + REACT_SLINGSHOT, + REACT_GUST_BELLOWS, + REACT_UNDERWATER, + REACT_4, + }; + + u32 getSceneFlag() { + return params & 0xFF; + } + + int getParam0x08() { + return (params >> 8) & 0xFF; + } + + s32 getParam0x10() { + return (params >> 0x10) & 0xF; + } + + bool getParam0x14() { + return (params >> 0x14) & 0x1; + } + + ReactType getReactType() { + return (ReactType)(params >> 0x1C); + } + + void onDelete(); + void checkForBonkItem(); + void checkForBubble(); + void checkForSlingBellowsItem(); + + bool fn_578_DB0(const mVec3_c &pos, u32 arg); + bool spawnHearts(s32 params, const mVec3_c &pos, s32 arg, mAng angle); + + STATE_MGR_DECLARE(dTgReaction_c); + dCcD_Cyl mCollision; + DowsingTarget mDowsingTarget; + + bool mHasDowsingTarget; + bool field_0x4DD; + bool field_0x4DE; + u32 field_0x4E0; + f32 field_0x4E4; }; #endif diff --git a/include/m/m_angle.h b/include/m/m_angle.h index 97033a08..6da39005 100644 --- a/include/m/m_angle.h +++ b/include/m/m_angle.h @@ -13,6 +13,14 @@ struct mAng { return mVal; } + mAng operator-() { + return mAng(-mVal); + } + + mAng operator+(const mAng &other) const { + return mAng(mVal + other.mVal); + } + mAng &operator+=(const mAng &other) { mVal += other.mVal; return *this; diff --git a/src/REL/d/a/obj/d_a_obj_spike.cpp b/src/REL/d/a/obj/d_a_obj_spike.cpp index 4f7a83dc..0031d51a 100644 --- a/src/REL/d/a/obj/d_a_obj_spike.cpp +++ b/src/REL/d/a/obj/d_a_obj_spike.cpp @@ -6,7 +6,7 @@ SPECIAL_ACTOR_PROFILE(OBJ_SPIKE, dAcOspike_c, fProfile::OBJ_SPIKE, 0x1D9, 0, 2); // clang-format off dCcD_SrcAabb dAcOspike_c::sCcSrc = { {{{0x400}, 0x2003F, 0, 1, 0, 0, 0, 0, 0}, - {{0xFEB77DFF}, 0x111, 0x60407, 0, 0}, + {{0xFEB77DFF}, 0x111, 0x06, 0x407, 0, 0}, {0}}, {-1.0f, -246.0f, -472.0f, 73.0f, 255.0f, 482.0f}}; // clang-format on diff --git a/src/REL/d/a/obj/d_a_obj_toD3_stone_figure.cpp b/src/REL/d/a/obj/d_a_obj_toD3_stone_figure.cpp index 7f665394..91c1b376 100644 --- a/src/REL/d/a/obj/d_a_obj_toD3_stone_figure.cpp +++ b/src/REL/d/a/obj/d_a_obj_toD3_stone_figure.cpp @@ -17,7 +17,7 @@ f32 dAcOtoD3StoneFigure_c::sHeight = 290.0f; // clang-format off dCcD_SrcCyl dAcOtoD3StoneFigure_c::sCcSrc = { {{{0}, 0, 0, 0, 0, 0, 0, 0, 0}, - {{0xFEB77DFF}, 0x1000111, 0x60407, 0, 0}, + {{0xFEB77DFF}, 0x1000111, 0x06, 0x407, 0, 0}, {0xE9}}, {dAcOtoD3StoneFigure_c::sRadius, dAcOtoD3StoneFigure_c::sHeight} }; diff --git a/src/REL/d/a/obj/d_a_obj_triforce.cpp b/src/REL/d/a/obj/d_a_obj_triforce.cpp index 36180d41..c79c143c 100644 --- a/src/REL/d/a/obj/d_a_obj_triforce.cpp +++ b/src/REL/d/a/obj/d_a_obj_triforce.cpp @@ -8,7 +8,7 @@ SPECIAL_ACTOR_PROFILE(OBJ_TRIFORCE, dAcOtriforce_c, fProfile::OBJ_TRIFORCE, 0x15 // clang-format off dCcD_SrcSph dAcOtriforce_c::sCcSrc = { {{{0}, 0, 0, 0, 0, 0, 0, 0, 0}, - {{0xFEB77DFF}, 0x111, 0x60407, 0, 0}, + {{0xFEB77DFF}, 0x111, 0x06, 0x407, 0, 0}, {0xE9}}, {150.0f}}; // clang-format on diff --git a/src/REL/d/t/d_t_reaction.cpp b/src/REL/d/t/d_t_reaction.cpp index 883f3ea7..eab2086f 100644 --- a/src/REL/d/t/d_t_reaction.cpp +++ b/src/REL/d/t/d_t_reaction.cpp @@ -1,9 +1,300 @@ +#include +#include +#include +#include +#include #include +#include -SPECIAL_ACTOR_PROFILE(TAG_REACTION, dTgReaction_c, fProfile::TAG_REACTION, 0x151, 0, 0); +SPECIAL_ACTOR_PROFILE(TAG_REACTION, dTgReaction_c, fProfile::TAG_REACTION, 0x0151, 0, 0); STATE_DEFINE(dTgReaction_c, Wait); +#pragma explicit_zero_data on +const u32 fZero = 0; +#pragma explicit_zero_data off +const f32 dTgReaction_c::sRadius = 100.0f; +const f32 dTgReaction_c::sHeight = 100.0f; + +// clang-format off +dCcD_SrcCyl dTgReaction_c::sCcSrc = { + {{{0}, 0, 0, 0, 0, 0, 0, 0, 0}, + {{0x10000}, 0x213, 0, 0x8, 0x8, 0}, + {0xE8}}, + {dTgReaction_c::sRadius, dTgReaction_c::sHeight} +}; +// clang-format on + +#pragma explicit_zero_data on +static u32 initialRotX = 0; +#pragma explicit_zero_data off + +bool dTgReaction_c::createHeap() { + return true; +} + +extern "C" bool isHeroMode(); +extern "C" u32 adventurePouchCountItem(u32 itemId); + +int dTgReaction_c::create() { + // Note the double _c here + if (!initAllocatorWork1Heap(0x1000, "dTgReaction_c_c::m_allocator", 0x20)) { + return FAILED; + } + + if (getReactType() != REACT_GUST_BELLOWS) { + if (getSceneFlag() >= 0xFF) { + return FAILED; + } + if (SceneflagManager::sInstance->checkBoolFlag(roomid, getSceneFlag())) { + return FAILED; + } + } + + field_0x4E0 = rotation.x & 0xFF; + angle.x = initialRotX; + rotation.x = angle.x; + if (field_0x4E0 < 0xFF && !SceneflagManager::sInstance->checkBoolFlag(roomid, field_0x4E0)) { + return FAILED; + } + + if (isHeroMode()) { + if (getParam0x10() == 1) { + field_0x4DE = 1; + } + + if (field_0x4DE) { + u32 heartMedalCount = adventurePouchCountItem(/* HEART_MEDAL*/ 100); + if (heartMedalCount == 0) { + return FAILED; + } else if (heartMedalCount == 1 && cM::rnd() < 0.5f) { + return FAILED; + } + } + } + + mCCdStruct.setField0x38(0); + mCollision.init(sCcSrc); + mCollision.initUnk(mCCdStruct); + + switch (getReactType()) { + case REACT_BONK: + mCollision.setTgFlag(0x80); + mCollision.setTgField0x0A(0); + mCollision.SetR(sCcSrc.mCylAttr.mRadius * mScale.x); + mCollision.SetH(mScale.y * sCcSrc.mCylAttr.mHeight); + break; + case REACT_SLINGSHOT: + mCollision.setTgFlag(0x10000); + mCollision.setTgField0x0A(8); + mCollision.SetR(sCcSrc.mCylAttr.mRadius * mScale.x); + mCollision.SetH(mScale.y * sCcSrc.mCylAttr.mHeight); + break; + case REACT_GUST_BELLOWS: + mCollision.setTgFlag(0x100000); + mCollision.setTgField0x0A(0); + mCollision.SetR(sCcSrc.mCylAttr.mRadius * mScale.x); + mCollision.SetH(mScale.y * sCcSrc.mCylAttr.mHeight); + break; + } + + int item = getParam0x10(); + if (item != 0xF) { + DowsingTarget::DowsingSlot slot; + if (item == 0) { + slot = DowsingTarget::SLOT_RUPEE; + } else if (item == 1) { + slot = DowsingTarget::SLOT_HEART; + } else { + return FAILED; + } + mVec3_c dwsOffset; + if (!getParam0x14()) { + field_0x4E4 = mScale.y * sCcSrc.mCylAttr.mHeight * 0.5f; + dwsOffset = mVec3_c(0.0f, 0.5f * sCcSrc.mCylAttr.mHeight, 0.0f); + } else { + dwsOffset = mVec3_c::Zero; + } + mDowsingTarget.initialize(slot, 0, &dwsOffset, 5000.0f); + mDowsingTarget.doRegister(); + mHasDowsingTarget = true; + } + + mStateMgr.changeState(StateID_Wait); + return SUCCEEDED; +} + +int dTgReaction_c::doDelete() { + onDelete(); + return SUCCEEDED; +} + +int dTgReaction_c::actorExecute() { + if (SceneflagManager::sInstance->checkBoolFlag(roomid, getSceneFlag())) { + onDelete(); + return SUCCEEDED; + } else { + mStateMgr.executeState(); + return SUCCEEDED; + } +} + +int dTgReaction_c::draw() { + return SUCCEEDED; +} void dTgReaction_c::initializeState_Wait() {} -void dTgReaction_c::executeState_Wait() {} +void dTgReaction_c::executeState_Wait() { + switch (getReactType()) { + case REACT_BONK: + case REACT_4: checkForBonkItem(); break; + case REACT_SLINGSHOT: + case REACT_GUST_BELLOWS: checkForSlingBellowsItem(); break; + case REACT_UNDERWATER: checkForBubble(); break; + } +} void dTgReaction_c::finalizeState_Wait() {} + +extern "C" void *SOUND_EFFECT_SOUND_MGR; +extern "C" void SmallSoundManager__playSound(void *, u16); + +void dTgReaction_c::checkForBonkItem() { + if (dAcPy_c::LINK != nullptr && dAcPy_c::LINK->checkFlags0x350(0x2000)) { + mVec3_c diff = position - dAcPy_c::LINK->position; + f32 dist = diff.x * diff.x + diff.z * diff.z; + f32 rad = mScale.x * 100.0f; + if (!(dist < rad * rad)) { + return; + } + + if (getReactType() == REACT_4) { + if (field_0x4DD == 0) { + mVec3_c c = mVec3_c::Ez * rad; + mVec3_c c2 = position; + c.rotY(rotation.y); + c2 += c; + c2.y += field_0x4E4; + u32 newItemParms = dAcItem_c::createItemParams(/* HEART_PIECE */ 0x5E, 1, 0, getSceneFlag(), 1, 0xFF); + if (dAcObjBase_c::create(fProfile::ITEM, roomid, newItemParms, &c2, nullptr, nullptr, 0xFFFFFFFF)) { + field_0x4DD = 1; + onDelete(); + SmallSoundManager__playSound(SOUND_EFFECT_SOUND_MGR, 0x13AD); + } + } + } else { + u32 uVar3; + mVec3_c pos = position; + int p = getParam0x08(); + if (p == 0) { + uVar3 = 6; + } else if (p == 0xFF) { + uVar3 = 5; + } else if (p == 1) { + uVar3 = 5; + mVec3_c c = mVec3_c::Ez * rad; + c.rotY(rotation.y); + pos += c; + } else { + uVar3 = 6; + } + + pos.y += field_0x4E4; + if (fn_578_DB0(pos, uVar3)) { + SmallSoundManager__playSound(SOUND_EFFECT_SOUND_MGR, 0x13AE); + } + SceneflagManager::sInstance->setFlag(roomid, getSceneFlag()); + onDelete(); + } + } +} + +void dTgReaction_c::checkForBubble() { + if (mCollision.someInteractCheck() && mCollision.CheckCollidedMask(0x100000)) { + if (dAcPy_c::LINK != nullptr && dAcPy_c::LINK->checkFlags0x350(0x40)) { + mVec3_c spawnPos = position; + dAcObjBase_c::create(fProfile::OBJ_BUBBLE, roomid, 0x4, &spawnPos, nullptr, nullptr, 0xFFFFFFFF); + } + } + mCollision.SetC(position); + ColliderManager::getColliderManager()->addCollider(&mCollision); +} + +// TODO move this somewhere +template +T rndRange(T min, T max) { + f32 r = cM::rndF(max - min); + f32 m = min; + m += r; + return m; +} + +void dTgReaction_c::checkForSlingBellowsItem() { + if (mCollision.someInteractCheck()) { + u32 uVar3; + // mVec3_c pos = position; + int p = getParam0x08(); + if (p == 0) { + uVar3 = 6; + } else { + uVar3 = p == 0xFF ? 5 : 6; + } + mVec3_c spawnPos = position; + spawnPos.y += field_0x4E4; + if (fn_578_DB0(spawnPos, uVar3)) { + SmallSoundManager__playSound(SOUND_EFFECT_SOUND_MGR, 0x13AE); + } + SceneflagManager::sInstance->setFlag(roomid, getSceneFlag()); + onDelete(); + } + mCollision.SetC(position); + ColliderManager::getColliderManager()->addCollider(&mCollision); +} + +void dTgReaction_c::onDelete() { + if (mHasDowsingTarget) { + mDowsingTarget.doUnregister(); + mHasDowsingTarget = false; + } +} + +bool dTgReaction_c::fn_578_DB0(const mVec3_c &position, u32 arg) {} + +bool dTgReaction_c::spawnHearts(s32 params, const mVec3_c &pos, s32 arg, mAng angle) { + int numHearts = params == 6 ? 3 : 1; + mAng3_c ang(0, 0, 0); + + // This is annoying because we don't know which operators + // mAng supports + mAng tmp1; + int tmp3; + if (arg == 6) { + tmp1 = angle; + static s32 SOME_ANG = -3641; + tmp3 = SOME_ANG; + } else { + tmp1 = cLib::targetAngleY(dAcPy_c::LINK->position, pos); + tmp3 = -0x8000; + tmp1 = tmp1 + mAng(0x4000); + } + + mAng tmp2 = tmp3; + s16 stepSize = tmp2 / numHearts; + tmp2 = stepSize / 2; + int step = tmp1 + tmp2; + tmp2 = mAng(tmp2 / 2); + + for (int i = 0; i < numHearts; i++) { + // Note: This is a (presumably templated) rndRange function + // that takes and returns a struct mAng + mAng offset = rndRange(-tmp2, tmp2); + ang.y = mAng(step) + offset; + if (arg == 5) { + dAcItem_c::spawnItem(/* HEART */ 0x6, roomid, pos, ang, 0xFFFFFFFF, 1); + } else if (arg == 6) { + dAcItem_c::spawnItem(/* HEART */ 0x6, roomid, pos, ang, 0xFFFFFFFF, 0); + } else { + dAcItem_c::spawnDrop(/* HEART */ 0x6, roomid, pos, ang); + } + step = mAng(step) - stepSize; + } + return true; +} diff --git a/src/d/col/cc/d_cc_d.cpp b/src/d/col/cc/d_cc_d.cpp index 146b3121..eb113b04 100644 --- a/src/d/col/cc/d_cc_d.cpp +++ b/src/d/col/cc/d_cc_d.cpp @@ -208,6 +208,10 @@ dAcBase_c *dCcD_GObjInf::GetAtActor() { return mGObjAt.getActor(); } +bool dCcD_GObjInf::CheckCollidedMask(u32 mask) { + return (mGObjTg.get0x58() & mask); +} + dAcBase_c *dCcD_GObjInf::GetTgActor() { return mGObjTg.getActor(); }