diff --git a/config/SOUE01/rels/d_t_reactionNP/symbols.txt b/config/SOUE01/rels/d_t_reactionNP/symbols.txt index 626c688f..370e3284 100644 --- a/config/SOUE01/rels/d_t_reactionNP/symbols.txt +++ b/config/SOUE01/rels/d_t_reactionNP/symbols.txt @@ -24,7 +24,7 @@ checkForSlingBellowsItem__13dTgReaction_cFv = .text:0x00000C50; // type:function onDelete__13dTgReaction_cFv = .text:0x00000D60; // type:function size:0x44 fn_578_DB0 = .text:0x00000DB0; // type:function size:0xB4 spawnHearts__13dTgReaction_cFlRC7mVec3_cl4mAng = .text:0x00000E70; // type:function size:0x184 -rndRange<4mAng>__F4mAng4mAng_4mAng = .text:0x00001000; // type:function size:0xA4 +rndRange<4mAng>__2cMF4mAng4mAng_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/splits.txt b/config/SOUE01/splits.txt index ff362c43..e14eb5f1 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -207,7 +207,10 @@ d/flag/flag_managers.cpp: toBeSorted/special_item_drop_mgr.cpp: .text start:0x800C7B60 end:0x800C82B0 + .rodata start:0x804E4CC8 end:0x804E4EE0 + .data start:0x80511C50 end:0x80511C60 .sbss start:0x80575438 end:0x80575440 + .sdata2 start:0x805799B8 end:0x80579AD0 d/lyt/meter/d_lyt_meter.cpp: .text start:0x800C8950 end:0x800DF8A8 diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 0b1714bb..9d424c41 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -4416,12 +4416,12 @@ Timekeeper__doCount = .text:0x800C7A20; // type:function size:0x130 fn_800C7B50 = .text:0x800C7B50; // type:function size:0x8 __ct__18SpecialItemDropMgrFv = .text:0x800C7B60; // type:function size:0x14 SpecialItemDropMgr__ctor = .text:0x800C7B80; // type:function size:0x30 -fn_800C7BB0__FP18SpecialItemDropMgri = .text:0x800C7BB0; // type:function size:0x150 -fn_800C7D00__FP18SpecialItemDropMgri = .text:0x800C7D00; // type:function size:0x1C -fn_800C7D20__FP18SpecialItemDropMgri = .text:0x800C7D20; // type:function size:0x1C -giveSpecialDropItem__FP18SpecialItemDropMgriiP7mVec3_ciPsi = .text:0x800C7D40; // type:function size:0x1A8 -spawnSpecialDropItem__FP18SpecialItemDropMgriiP7mVec3_ciPs = .text:0x800C7EF0; // type:function size:0x2D8 -fn_800C81D0__Fsss = .text:0x800C81D0; // type:function size:0x98 +fn_800C7BB0__18SpecialItemDropMgrFi = .text:0x800C7BB0; // type:function size:0x150 +shouldTryExtraHearts__18SpecialItemDropMgrFi = .text:0x800C7D00; // type:function size:0x1C +shouldTryExtraRupees__18SpecialItemDropMgrFi = .text:0x800C7D20; // type:function size:0x1C +giveSpecialDropItem__18SpecialItemDropMgrFiiP7mVec3_ci4mAngl = .text:0x800C7D40; // type:function size:0x1A8 +spawnSpecialDropItem__18SpecialItemDropMgrFiiP7mVec3_ci4mAng = .text:0x800C7EF0; // type:function size:0x2D8 +rndRange<4mAng>__2cMF4mAng4mAng_4mAng = .text:0x800C81D0; // type:function size:0x98 __dt__18SpecialItemDropMgrFv = .text:0x800C8270; // type:function size:0x40 isShortNegative = .text:0x800C82B0; // type:function size:0x18 0x3FFFMask = .text:0x800C82D0; // type:function size:0x18 @@ -13546,7 +13546,7 @@ fn_80251940 = .text:0x80251940; // type:function size:0xA8 AcItem__getCurrentOffset = .text:0x802519F0; // type:function size:0xA0 AcItem__getPositionOffset = .text:0x80251A90; // type:function size:0x5C fn_80251AF0 = .text:0x80251AF0; // type:function size:0x78 -AcItem__checkFlag = .text:0x80251B70; // type:function size:0x128 +checkFlag__9dAcItem_cFUl = .text:0x80251B70; // type:function size:0x128 AcItem__setFlag = .text:0x80251CA0; // type:function size:0xC0 AcItem__checkFlagForItem = .text:0x80251D60; // type:function size:0x34 AcItem__checkItemFlag = .text:0x80251DA0; // type:function size:0x48 @@ -28233,7 +28233,7 @@ lbl_804E4CB8 = .rodata:0x804E4CB8; // type:object size:0x10 data:float lbl_804E4CC8 = .rodata:0x804E4CC8; // type:object size:0x10 lbl_804E4CD8 = .rodata:0x804E4CD8; // type:object size:0x1B0 lbl_804E4E88 = .rodata:0x804E4E88; // type:object size:0x20 data:4byte -SPECIAL_ITEM_ARRAY = .rodata:0x804E4EA8; // type:object size:0x38 +SPECIAL_ITEM_ARRAY = .rodata:0x804E4EA8; // type:object size:0x32 btn1BrlanMap = .rodata:0x804E4EE0; // type:object size:0x18 scope:local data:4byte lbl_804E4EF8 = .rodata:0x804E4EF8; // type:object size:0x18 data:4byte lbl_804E4F10 = .rodata:0x804E4F10; // type:object size:0x110 data:4byte @@ -31041,7 +31041,7 @@ lbl_80511C00 = .data:0x80511C00; // type:object size:0x10 lbl_80511C10 = .data:0x80511C10; // type:object size:0x10 lbl_80511C20 = .data:0x80511C20; // type:object size:0x10 Timekeeper__vtable = .data:0x80511C30; // type:object size:0x20 -SpecialItemDropMgr__vtable = .data:0x80511C50; // type:object size:0x10 +__vt__18SpecialItemDropMgr = .data:0x80511C50; // type:object size:0xC lbl_80511C60 = .data:0x80511C60; // type:object size:0x14 lbl_80511C74 = .data:0x80511C74; // type:object size:0xC lbl_80511C80 = .data:0x80511C80; // type:object size:0x1C @@ -39954,7 +39954,7 @@ lbl_80575418 = .sbss:0x80575418; // type:object size:0x8 lbl_80575420 = .sbss:0x80575420; // type:object size:0x8 data:byte lbl_80575428 = .sbss:0x80575428; // type:object size:0x8 data:byte lbl_80575430 = .sbss:0x80575430; // type:object size:0x8 data:4byte -SpecialItemDropMgr__sInstance = .sbss:0x80575438; // type:object size:0x8 data:4byte +sInstance__18SpecialItemDropMgr = .sbss:0x80575438; // type:object size:0x4 data:4byte FOR_LOADED_PARTICLES = .sbss:0x80575440; // type:object size:0x8 data:4byte sInstance__20dLytMeterContainer_c = .sbss:0x80575448; // type:object size:0x8 data:4byte lbl_80575450 = .sbss:0x80575450; // type:object size:0x8 data:4byte diff --git a/include/c/c_math.h b/include/c/c_math.h index 8b95bf71..ee21fe0d 100644 --- a/include/c/c_math.h +++ b/include/c/c_math.h @@ -11,7 +11,14 @@ int rndInt(int max); f32 rndF(f32 max); f32 rndFX(f32 amp); -template +template +T rndRange(T min, T max) { + f32 r = cM::rndF(max - min); + f32 m = min; + m += r; + return m; +} + inline T minMaxLimit(T val, T min, T max) { return (T)((T)val < (T)min ? (T)min : ((T)val > (T)max ? (T)max : (T)val)); } diff --git a/include/d/a/d_a_player.h b/include/d/a/d_a_player.h index 57471a06..666a5365 100644 --- a/include/d/a/d_a_player.h +++ b/include/d/a/d_a_player.h @@ -99,7 +99,7 @@ class dAcPy_c : public dAcObjBase_c { /* vt 0x144 */ virtual void setActorLinkToSomething(); /* vt 0x148 */ virtual void applyDamageWithIFrames(); /* vt 0x14C */ virtual void vt_0x14C(); - /* vt 0x150 */ virtual void hasLessThanQuarterHealth(); + /* vt 0x150 */ virtual bool hasLessThanQuarterHealth(bool); /* vt 0x154 */ virtual void vt_0x154(); /* vt 0x158 */ virtual void vt_0x158(); /* vt 0x15C */ virtual void vt_0x15C(); diff --git a/include/d/a/obj/d_a_obj_item.h b/include/d/a/obj/d_a_obj_item.h index 4a2cf494..fc0cb063 100644 --- a/include/d/a/obj/d_a_obj_item.h +++ b/include/d/a/obj/d_a_obj_item.h @@ -12,6 +12,8 @@ class dAcItem_c : public dAcObjBase_c { 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); + + static u32 checkFlag(u32 flag); }; #endif diff --git a/include/toBeSorted/special_item_drop_mgr.h b/include/toBeSorted/special_item_drop_mgr.h index 492f0725..8132cff0 100644 --- a/include/toBeSorted/special_item_drop_mgr.h +++ b/include/toBeSorted/special_item_drop_mgr.h @@ -2,6 +2,7 @@ #define SPECIAL_ITEM_DROP_MGR_H #include "common.h" +#include "m/m_angle.h" #include "m/m_vec.h" class SpecialItemDropMgr { @@ -9,16 +10,15 @@ class SpecialItemDropMgr { static SpecialItemDropMgr *sInstance; SpecialItemDropMgr(); - static int fn_800C7BB0(SpecialItemDropMgr *mgr, int specialItemId); - static short fn_800C7D00(SpecialItemDropMgr *mgr, int specialItemId); - static short fn_800C7D20(SpecialItemDropMgr *mgr, int specialItemId); - static int giveSpecialDropItem( - SpecialItemDropMgr *mgr, int specialItemId, int roomid, mVec3_c *pos, int subtype, s16 *rot, s32 unused - ); - static bool - spawnSpecialDropItem(SpecialItemDropMgr *mgr, int specialItemId, int roomid, mVec3_c *pos, int subtype, s16 *rot); - static void fn_800C81D0(s16, s16, s16); - ~SpecialItemDropMgr(); + virtual ~SpecialItemDropMgr() {} + + static SpecialItemDropMgr *create(); + + int fn_800C7BB0(int specialItemId); + bool shouldTryExtraHearts(int specialItemId); + bool shouldTryExtraRupees(int specialItemId); + int giveSpecialDropItem(int specialItemId, int roomid, mVec3_c *pos, int subtype, mAng rot, s32 unused); + bool spawnSpecialDropItem(int specialItemId, int roomid, mVec3_c *pos, int subtype, mAng rot); }; #endif 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 9bcff77a..67e875e3 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 @@ -1,6 +1,7 @@ #include "d/a/obj/d_a_obj_toD3_stone_figure.h" #include "d/col/cc/d_cc_s.h" +#include "d/a/obj/d_a_obj_item.h" #include "d/flag/storyflag_manager.h" #include "toBeSorted/attention.h" #include "toBeSorted/event.h" @@ -163,7 +164,6 @@ void dAcOtoD3StoneFigure_c::doInteraction(s32 arg) { } } -extern "C" s32 AcItem__checkFlag(s32); bool dAcOtoD3StoneFigure_c::hasStoneOfTrials() const { - return AcItem__checkFlag(0xB4); + return dAcItem_c::checkFlag(0xB4); } diff --git a/src/REL/d/t/d_t_reaction.cpp b/src/REL/d/t/d_t_reaction.cpp index 5f982281..5e0db3ac 100644 --- a/src/REL/d/t/d_t_reaction.cpp +++ b/src/REL/d/t/d_t_reaction.cpp @@ -221,25 +221,17 @@ void dTgReaction_c::checkForBubble() { dCcS::GetInstance()->Set(&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.ChkTgHit()) { u8 p = getParam0x08(); u32 uVar3; if (p == 0) { uVar3 = 6; - } else if (uVar3 == 0xFF) { - uVar3 = 5; } else { uVar3 = 6; + if ((int)p == 0xFF) { + uVar3 = 5; + } } mVec3_c spawnPos = position; spawnPos.y += field_0x4E4; @@ -287,9 +279,7 @@ bool dTgReaction_c::spawnHearts(s32 params, const mVec3_c &pos, s32 arg, mAng an 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); + mAng offset = cM::rndRange(-tmp2, tmp2); ang.y = mAng(step) + offset; if (arg == 5) { dAcItem_c::spawnItem(/* HEART */ 0x6, roomid, pos, ang, 0xFFFFFFFF, 1); diff --git a/src/d/a/d_a_base.cpp b/src/d/a/d_a_base.cpp index 30581cee..cf0f361d 100644 --- a/src/d/a/d_a_base.cpp +++ b/src/d/a/d_a_base.cpp @@ -243,9 +243,8 @@ u32 dAcBase_c::itemDroppingAndGivingRelated(mVec3_c *spawnPos, int subtype) { u32 param2Copy = params2; params2 = param2Copy | 0xFF000000; // mAng3_c rot = {}; - s16 rot = 0; - return SpecialItemDropMgr::giveSpecialDropItem( - SpecialItemDropMgr::sInstance, param2Copy >> 0x18, roomid, spawnPos, subtype, &rot, -1 + return SpecialItemDropMgr::sInstance->giveSpecialDropItem( + param2Copy >> 0x18, roomid, spawnPos, subtype, 0, -1 ); } diff --git a/src/toBeSorted/special_item_drop_mgr.cpp b/src/toBeSorted/special_item_drop_mgr.cpp index 25940a21..7d4c8613 100644 --- a/src/toBeSorted/special_item_drop_mgr.cpp +++ b/src/toBeSorted/special_item_drop_mgr.cpp @@ -1,51 +1,514 @@ #include "toBeSorted/special_item_drop_mgr.h" +#include "c/c_lib.h" +#include "c/c_math.h" +#include "common.h" #include "d/a/d_a_player.h" -#include "m/m_Angle.h" +#include "d/a/obj/d_a_obj_item.h" +#include "m/m_angle.h" #include "m/m_vec.h" SpecialItemDropMgr *SpecialItemDropMgr::sInstance = nullptr; -extern "C" short targetAngleY(mVec3_c *, mVec3_c *); -extern "C" int rndInt(int); -extern "C" void spawnItem1(s16 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); -extern "C" void spawnItem2(s16 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); -extern "C" void spawnItem3(s16 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); -extern "C" void spawnItem4(s16 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); -extern "C" void spawnItem5(s16 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); -extern "C" void spawnItem6(s16 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); -extern "C" void spawnItem7(s16 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); -extern "C" void spawnItem8(s16 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); -extern "C" void spawnItem9(s16 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); +extern "C" void spawnItem1(u32 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); +extern "C" void spawnItem2(u32 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); +extern "C" void spawnItem3(u32 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); +extern "C" void spawnItem4(u32 itemid, u32, u32 param2); +extern "C" void spawnItem5(u32 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); +extern "C" void spawnItem6(u32 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); +extern "C" void spawnItem7(u32 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, u32 param2, u32 unk); +extern "C" void spawnItem8(u32 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot, void *, void *, u32 param2, u32 unk); +extern "C" void spawnItem9(u32 itemid, u32 roomid, mVec3_c *pos, mAng3_c *rot); // 800c7b80 SpecialItemDropMgr::SpecialItemDropMgr() { SpecialItemDropMgr::sInstance = this; } +SpecialItemDropMgr *SpecialItemDropMgr::create() { + return new SpecialItemDropMgr(); +} + +struct DropEntry { + /* 0x0 */ u8 mEntryIndex; + /* 0x1 */ u8 mDropChance; +}; + +struct DropList { + /* 0x0 */ u16 mLen; + /* 0x2 */ u16 mFlags; + /* 0x4 */ const DropEntry *mpEntries; +}; + +static const DropEntry e01[] = { + {0x01, 20}, + {0x03, 40}, + {0x04, 10}, +}; + +static const DropEntry e02[] = { + {0x01, 20}, + {0x03, 10}, + {0x04, 40}, +}; + +static const DropEntry e03[] = { + {0x01, 20}, + {0x04, 25}, + {0x05, 25}, +}; + +static const DropEntry e04[] = { + {0x01, 100}, +}; + +static const DropEntry e05[] = { + {0x01, 60}, + {0x02, 10}, +}; + +static const DropEntry e06[] = { + {0x02, 100}, +}; + +static const DropEntry e07[] = { + {0x03, 40}, + {0x04, 10}, +}; + +static const DropEntry e08[] = { + {0x03, 50}, + {0x04, 40}, + {0x05, 10}, +}; + +static const DropEntry e09[] = { + {0x04, 70}, + {0x05, 30}, +}; + +static const DropEntry e10[] = { + {0x06, 100}, +}; + +static const DropEntry e11[] = { + {0x08, 100}, +}; + +static const DropEntry e12[] = { + {0x0A, 100}, +}; + +static const DropEntry e13[] = { + {0x0B, 100}, +}; + +static const DropEntry e14[] = { + {0x0C, 100}, +}; + +static const DropEntry e15[] = { + {0x0D, 100}, +}; + +static const DropEntry e16[] = { + {0x03, 7}, + {0x04, 3}, +}; + +static const DropEntry e17[] = { + {0x01, 7}, + {0x03, 3}, +}; + +static const DropEntry e18[] = { + {0x03, 100}, +}; + +static const DropEntry e19[] = { + {0x04, 100}, +}; + +static const DropEntry e20[] = { + {0x05, 100}, +}; + +static const DropEntry e21[] = { + {0x0E, 100}, +}; + +static const DropEntry e22[] = { + {0x0F, 100}, +}; + +static const DropEntry e23[] = { + {0x03, 60}, + {0x04, 30}, + {0x0F, 10}, +}; + +static const DropEntry e24[] = { + {0x03, 30}, + {0x04, 30}, + {0x05, 20}, + {0x0F, 20}, +}; + +static const DropEntry e25[] = { + {0x10, 100}, +}; + +static const DropEntry e26[] = { + {0x12, 100}, +}; + +static const DropEntry e27[] = { + {0x13, 100}, +}; + +static const DropEntry e28[] = { + {0x14, 100}, +}; + +static const DropEntry e29[] = { + {0x10, 10}, +}; + +static const DropEntry e30[] = { + {0x0B, 100}, +}; + +static const DropEntry e31[] = { + {0x01, 100}, +}; + +static const DropEntry e32[] = { + {0x01, 12}, +}; + +static const DropEntry e33[] = { + {0x01, 35}, +}; + +static const DropEntry e34[] = { + {0x16, 30}, + {0x15, 10}, + {0x02, 20}, + {0x01, 20}, +}; + +static const DropEntry e35[] = { + {0x15, 100}, +}; + +static const DropEntry e36[] = { + {0x16, 100}, +}; + +static const DropEntry e37[] = { + {0x01, 20}, + {0x03, 30}, + {0x04, 15}, +}; + +static const DropEntry e38[] = { + {0x04, 30}, + {0x05, 5}, + {0x03, 45}, +}; + +static const DropEntry e39[] = { + {0x01, 10}, +}; + +static const DropEntry e40[] = { + {0x03, 10}, + {0x04, 5}, +}; + +static const DropEntry e41[] = { + {0x17, 100}, +}; + +static const DropEntry e42[] = { + {0x01, 20}, +}; + +static const DropEntry e44[] = { + {0x01, 7}, +}; + +static const DropEntry e45[] = { + {0x03, 14}, + {0x04, 6}, +}; + +static const DropEntry e46[] = { + {0x01, 7}, + {0x03, 13}, +}; + +static const DropEntry e47[] = { + {0x18, 100}, +}; + +static const DropEntry e48[] = { + {0x01, 7}, +}; + +static const DropEntry e49[] = { + {0x01, 14}, +}; + +static const DropEntry e50[] = { + {0x01, 50}, +}; + +static const DropEntry e51[] = { + {0x0B, 20}, + {0x03, 20}, + {0x04, 10}, +}; + +static const DropEntry e52[] = { + {0x0A, 60}, + {0x01, 20}, + {0x04, 20}, +}; + +static const DropEntry e53[] = { + {0x08, 20}, + {0x0A, 20}, + {0x0B, 20}, + {0x03, 10}, + {0x04, 5}, +}; + +#define FLAG_EXTRA_HEARTS 1 +#define FLAG_EXTRA_RUPEES 2 + +#define FLAG_EXTRA_ALL (FLAG_EXTRA_HEARTS | FLAG_EXTRA_RUPEES) + +static const DropList sList[] = { + {0, 0, nullptr}, + {3, FLAG_EXTRA_ALL, e01}, + {3, FLAG_EXTRA_ALL, e02}, + {3, FLAG_EXTRA_ALL, e03}, + {1, FLAG_EXTRA_ALL, e04}, + {2, FLAG_EXTRA_ALL, e05}, + {1, FLAG_EXTRA_ALL, e06}, + {2, FLAG_EXTRA_ALL, e07}, + {3, FLAG_EXTRA_ALL, e08}, + {2, FLAG_EXTRA_ALL, e09}, + {1, 0, e10}, + {1, 0, e11}, + {1, 0, e12}, + {1, 0, e13}, + {1, 0, e14}, + {1, 0, e15}, + {2, FLAG_EXTRA_ALL, e16}, + {2, FLAG_EXTRA_ALL, e17}, + {1, 0, e18}, + {1, 0, e19}, + {1, 0, e20}, + {1, 0, e21}, + {1, 0, e22}, + {3, FLAG_EXTRA_ALL, e23}, + {4, FLAG_EXTRA_ALL, e24}, + {1, 0, e25}, + {1, 0, e26}, + {1, 0, e27}, + {1, 0, e28}, + {1, 0, e29}, + {1, 0, e30}, + {1, FLAG_EXTRA_ALL, e31}, + {1, FLAG_EXTRA_ALL, e32}, + {1, FLAG_EXTRA_ALL, e33}, + {4, FLAG_EXTRA_ALL, e34}, + {1, 0, e35}, + {1, 0, e36}, + {3, FLAG_EXTRA_ALL, e37}, + {3, FLAG_EXTRA_ALL, e38}, + {1, 0, e39}, + {2, 0, e40}, + {1, 0, e41}, + {1, FLAG_EXTRA_HEARTS, e42}, + {0, 0, nullptr}, + {1, FLAG_EXTRA_HEARTS, e44}, + {2, FLAG_EXTRA_ALL, e45}, + {2, FLAG_EXTRA_ALL, e46}, + {1, 0, e47}, + {1, FLAG_EXTRA_HEARTS, e48}, + {1, FLAG_EXTRA_HEARTS, e49}, + {1, 0, e50}, + {3, FLAG_EXTRA_ALL, e51}, + {3, 0, e52}, + {5, FLAG_EXTRA_RUPEES, e53}, +}; + +struct LowHealthReplacement { + s32 mOriginalIdx; + s32 mReplacementIndex; +}; + +const LowHealthReplacement LOW_HEALTH_REPLACEMENTS[] = { + { + 0x10, 0x11, + }, + { + 0x1E, 0x1F, + }, + { + 0x2B, 0x2C, + }, + { + 0x2D, 0x2E, + }, +}; + // TODO: Convert to enum once work on items has started -int SPECIAL_ITEM_ARRAY[28] = {0, 6, 6, 2, 3, 4, 0x2b, 0x28, 0x29, 7, 8, 0x39, 0, 0, - 0x1c, 0xa5, 58, 59, 183, 184, 185, 72, 72, 1, 34, 0, 0, 0}; -int RAND_RUPEE_ARRAY[4] = {2, 3, 4, 0}; +static const u16 SPECIAL_ITEM_ARRAY[] = { + 0, // None + 6, // Heart + 6, // Heart + 2, // Green Rupee + 3, // Blue Rupee + 4, // Red Rupee + 0x2b, // Farore Tear + 0x28, // 5 Bombs + 0x29, // 10 Bombs + 7, // Single Arrow + 8, // Bundle Arrows + 0x39, // 5 Deku Seeds + 0, // None + 0, // None + 0x1c, // ET Key Piece + 0xa5, // Eldin Ore + 58, // ??? + 59, // ??? + 183, // ??? + 184, // ??? + 185, // ??? + 72, // Fairy + 72, // Fairy + 1, // Small Key + 34, // Rupoor +}; + +static const u32 sNumDropEntries = 0x36; +static const struct { + u16 mNumEntries; + const DropList *mList; +} sDropTable = { + 0x36, + sList, +}; + +static const u16 RAND_RUPEE_ARRAY[] = {2, 3, 4}; + +extern "C" int getCurrentBowType(); +extern "C" int getCurrentSlingshotType(); +extern "C" bool isHeroMode(); // 800c7bb0 -int fn_800C7BB0(SpecialItemDropMgr *mgr, int specialItemId) {} +int SpecialItemDropMgr::fn_800C7BB0(int specialItemId) { + const DropList *list = &sDropTable.mList[specialItemId]; + const DropEntry *e = list->mpEntries; + int random = cM::rndInt(100); + + int acc = 0; + + for (int i = 0; i < list->mLen; i++) { + int entryIdx = e->mEntryIndex; + int weight = e->mDropChance; + + if (entryIdx == 9 || entryIdx == 10) { + if (getCurrentBowType() == 0) { + // No arrows until you get the Bow + weight = 0; + } + } else if (entryIdx == 11) { + if (getCurrentSlingshotType() == 0) { + // No seeds until you get the Slingshot + weight = 0; + } + } else if (specialItemId != 0x27 && (entryIdx == 1 || entryIdx == 2) && isHeroMode()) { + // Hearts generally don't drop on Hero Mode unless it's a special kind of heart (which?) + weight = 0; + } else if ((entryIdx == 7 || entryIdx == 8) && !dAcItem_c::checkFlag(/* Bomb Bag */ 92)) { + // Bombs won't drop until you get the Bomb Bag + weight = 0; + } -// 800c7d00 -short fn_800C7D00(SpecialItemDropMgr *mgr, int specialItemId) {} + if (weight != 0) { + int x = 0x1E / weight; + acc += weight; + if (x != 0) { + int tmp = x <= 3 ? x : 3; + if (random % tmp != 0) { + return 0; + } + } + + if (random < acc) { + return entryIdx; + } + } + e++; + } + + return 0; +} + +bool SpecialItemDropMgr::shouldTryExtraHearts(int specialItemId) { + return sDropTable.mList[specialItemId].mFlags & FLAG_EXTRA_HEARTS; +} +bool SpecialItemDropMgr::shouldTryExtraRupees(int specialItemId) { + return sDropTable.mList[specialItemId].mFlags & FLAG_EXTRA_RUPEES; +} -// 800c7d20 -short fn_800C7D20(SpecialItemDropMgr *mgr, int specialItemId) {} +extern "C" bool adventurePouchCountItem(u32 itemId); // 800c7d40 -int giveSpecialDropItem( - SpecialItemDropMgr *mgr, int specialItemId, int roomid, mVec3_c *pos, int subtype, s16 *rot, s32 unused -) {} +int SpecialItemDropMgr::giveSpecialDropItem( + int specialItemId, int roomid, mVec3_c *pos, int subtype, mAng rot, s32 unused +) { + if (specialItemId == 0xFF) { + return 0; + } + + for (u32 i = 0; i < 4; i++) { + const LowHealthReplacement &entry = LOW_HEALTH_REPLACEMENTS[i]; + if (specialItemId == entry.mOriginalIdx && dAcPy_c::LINK->hasLessThanQuarterHealth(false)) { + specialItemId = entry.mReplacementIndex; + break; + } + } + + bool ret = spawnSpecialDropItem(specialItemId, roomid, pos, subtype, rot); + if (shouldTryExtraHearts(specialItemId)) { + for (u32 i = 0; i < adventurePouchCountItem(/* HEART_MEDAL */ 100); i++) { + bool ok = spawnSpecialDropItem(0x27, roomid, pos, subtype, rot); + ret |= ok; + } + } + + if (shouldTryExtraRupees(specialItemId)) { + for (u32 i = 0; + i < adventurePouchCountItem(/* RUPEE_MEDAL */ 101) + adventurePouchCountItem(/* CURSED_MEDAL */ 104); + i++) { + bool ok = spawnSpecialDropItem(0x28, roomid, pos, subtype, rot); + ret |= ok; + } + } + + return ret; +} // 800c7ef0 // Very unmatching. Just here as a starting point -bool spawnSpecialDropItem(SpecialItemDropMgr *mgr, int specialItemId, int roomid, mVec3_c *pos, int subtype, s16 *rot) { - u32 unk = fn_800C7BB0(mgr, specialItemId); +bool SpecialItemDropMgr::spawnSpecialDropItem(int specialItemId, int roomid, mVec3_c *pos, int subtype, mAng rot) { + s32 unk = fn_800C7BB0(specialItemId); if (unk == 0) { return false; } @@ -61,31 +524,31 @@ bool spawnSpecialDropItem(SpecialItemDropMgr *mgr, int specialItemId, int roomid itemCount = 2; } - s16 currentRot; - s16 tempOther; - u16 itemid = SPECIAL_ITEM_ARRAY[unk]; + mAng currentRot; + mAng tempOther; + u32 itemid = SPECIAL_ITEM_ARRAY[unk]; mAng3_c itemRot(0, 0, 0); if (subtype == 2 || subtype == 6) { - currentRot = *rot; + currentRot = rot; tempOther = -0xe39; } else { - currentRot = targetAngleY(&(dAcPy_c::LINK->position), pos); + currentRot = cLib::targetAngleY(dAcPy_c::LINK->position, *pos); tempOther = -0x8000; currentRot += 0x4000; } - s16 angleDecrement = tempOther / itemCount; + // This angle code is annoying. d_t_reaction has similar code + s32 angleDecrement = tempOther / itemCount; tempOther = angleDecrement / 2; currentRot += tempOther; - tempOther /= 2; + tempOther = tempOther / 2; - for (s8 currentItemIndex = 0; currentItemIndex < itemCount; currentItemIndex++) { - s16 out; - SpecialItemDropMgr::fn_800C81D0(out, tempOther, -tempOther); + for (int currentItemIndex = 0; currentItemIndex < itemCount; currentItemIndex++) { + mAng out = cM::rndRange(tempOther, -tempOther); itemRot.y = currentRot + out; - if (unk < 15) { - itemid = RAND_RUPEE_ARRAY[rndInt(3)]; + if (unk >= 12 && unk < 14) { + itemid = RAND_RUPEE_ARRAY[cM::rndInt(3)]; spawnItem1(itemid, roomid, pos, &itemRot, 0xFFFFFFFF, 0); } else if (subtype == 2) { spawnItem2(itemid, roomid, pos, &itemRot, 0xFFFFFFFF, 0); @@ -93,7 +556,7 @@ bool spawnSpecialDropItem(SpecialItemDropMgr *mgr, int specialItemId, int roomid if (subtype == 1) { spawnItem3(itemid, roomid, pos, &itemRot, 0xFFFFFFFF, 0); } else if (subtype == 4) { - spawnItem4(itemid, roomid, pos, &itemRot, 0xFFFFFFFF, 0); + spawnItem4(itemid, 0, 0xFFFFFFFF); } else if (subtype == 3) { spawnItem5(itemid, roomid, pos, &itemRot, 0xFFFFFFFF, 0); } else if (subtype == 5) { @@ -101,18 +564,15 @@ bool spawnSpecialDropItem(SpecialItemDropMgr *mgr, int specialItemId, int roomid } else if (subtype == 6) { spawnItem7(itemid, roomid, pos, &itemRot, 0xFFFFFFFF, 0); } else if (subtype == 7) { - spawnItem8(itemid, roomid, pos, &itemRot, 0xFFFFFFFF, 0); + spawnItem8(itemid, roomid, pos, &itemRot, nullptr, nullptr, 0xFFFFFFFF, 0); } else { - spawnItem9(itemid, roomid, pos, &itemRot, 0xFFFFFFFF, 0); + spawnItem9(itemid, roomid, pos, &itemRot); } } - currentRot -= angleDecrement; + currentRot.mVal -= angleDecrement; } return true; } -// 800c81d0 -void fn_800C81D0(s16, s16, s16){}; - // 800c8270 -SpecialItemDropMgr::~SpecialItemDropMgr() {} +// SpecialItemDropMgr::~SpecialItemDropMgr() {}