From f4163de0dec401c21b28d78069ac659c2303d2de Mon Sep 17 00:00:00 2001 From: gymnast86 Date: Fri, 28 Aug 2026 22:08:25 -0700 Subject: [PATCH] update item service and fix master sword checks --- mods/randomizer/src/hooks.cpp | 30 ++++++++++++++++++++------ sdk/include/mods/svc/item.h | 4 +++- src/d/actor/d_a_demo_item.cpp | 2 +- src/d/actor/d_a_obj_item.cpp | 2 +- src/d/actor/d_a_obj_life_container.cpp | 4 ++-- src/d/actor/d_a_obj_master_sword.cpp | 11 +++------- src/d/actor/d_a_obj_smallkey.cpp | 2 +- src/d/actor/d_a_shop_item.cpp | 2 +- src/dusk/mods/item.hpp | 1 + src/dusk/mods/item_checks.cpp | 4 ++++ src/dusk/mods/item_gives.cpp | 2 ++ 11 files changed, 42 insertions(+), 22 deletions(-) diff --git a/mods/randomizer/src/hooks.cpp b/mods/randomizer/src/hooks.cpp index 3ee285b804..c90d863292 100644 --- a/mods/randomizer/src/hooks.cpp +++ b/mods/randomizer/src/hooks.cpp @@ -14,6 +14,7 @@ #include #include +#include "Z2AudioLib/Z2SceneMgr.h" #include "c/c_damagereaction.h" #include "d/actor/d_a_alink.h" #include "d/actor/d_a_b_bq.h" @@ -33,18 +34,20 @@ #include "d/actor/d_a_npc_zrc.h" #include "d/actor/d_a_npc_zrz.h" #include "d/actor/d_a_obj_bosswarp.h" -#include "d/actor/d_a_shop_item.h" -#include "d/actor/d_a_obj_swBallC.h" -#include "d/actor/d_a_obj_zra_rock.h" -#include "d/actor/d_a_tag_kmsg.h" -#include "d/actor/d_a_tbox2.h" #include "d/actor/d_a_obj_item.h" #include "d/actor/d_a_obj_life_container.h" +#include "d/actor/d_a_obj_master_sword.h" +#include "d/actor/d_a_obj_swBallC.h" +#include "d/actor/d_a_obj_zra_rock.h" +#include "d/actor/d_a_shop_item.h" +#include "d/actor/d_a_tag_kmsg.h" +#include "d/actor/d_a_tbox2.h" #include "d/d_door_param2.h" #include "d/d_event.h" #include "d/d_file_sel_info.h" #include "d/d_file_select.h" #include "d/d_gameover.h" +#include "d/d_item.h" #include "d/d_menu_item_explain.h" #include "d/d_menu_ring.h" #include "d/d_meter2_info.h" @@ -53,10 +56,8 @@ #include "d/d_s_play.h" #include "d/d_save.h" #include "d/d_shop_system.h" -#include "d/d_item.h" #include "f_op/f_op_overlap_mng.h" #include "m_Do/m_Do_Reset.h" -#include "Z2AudioLib/Z2SceneMgr.h" DEFINE_HOOK(&dFile_select_c::selectDataNameMove, dFile_select_c__selectDataNameMove); DEFINE_HOOK(&dFile_select_c::dataSelect, dFile_select_c__dataSelect); @@ -209,6 +210,8 @@ DEFINE_HOOK_SYMBOL("dComIfGs_getCollectSmell", u8(), getCollectSmell); DEFINE_HOOK(&dEvt_control_c::skipper, dEvt_control_c__skipper); +DEFINE_HOOK(&daObjMasterSword_c::executeWait, daObjMasterSword_c__executeWait); + namespace randomizer::ui { dialogSelectModeState g_dialogSelectModeState = SelectReady; } @@ -3338,6 +3341,15 @@ void hookReplaceEvtControlSkipper(ModContext*, void* args, void* retval, void*) *static_cast(retval) = doSkip; } +void hookPostMasterSwordExecuteWait(ModContext*, void* args, void* retval, void*) { + auto objMasterSword = mods::arg(args, 0); + + if (fopAcM_checkCarryNow(objMasterSword)) { + dComIfGs_onTmpBit(0x820); + objMasterSword->actor_status = 0; + } +} + } ModResult initialize() { @@ -3501,6 +3513,8 @@ ModResult initialize() { ADD_HOOK_REPLACE(dEvt_control_c__skipper, hookReplaceEvtControlSkipper); + ADD_HOOK_POST(daObjMasterSword_c__executeWait, hookPostMasterSwordExecuteWait); + return MOD_OK; } @@ -3636,6 +3650,8 @@ ModResult uninstall() { mods::hook::uninstall(svc_hook); + mods::hook::uninstall(svc_hook); + return MOD_OK; } } diff --git a/sdk/include/mods/svc/item.h b/sdk/include/mods/svc/item.h index 67d64cc6f2..ff4f31b547 100644 --- a/sdk/include/mods/svc/item.h +++ b/sdk/include/mods/svc/item.h @@ -8,7 +8,7 @@ #define ITEM_SERVICE_ID "dev.twilitrealm.dusklight.item" #define ITEM_SERVICE_MAJOR 2u -#define ITEM_SERVICE_MINOR 2u +#define ITEM_SERVICE_MINOR 3u /* 0 is never a valid handle. */ typedef uint64_t ItemCheckHandle; @@ -32,11 +32,13 @@ typedef struct ItemCheckInfo { uint8_t vanilla_item; uint8_t current_item; uint8_t current_display_item; + bool was_resolved; } ItemCheckInfo; typedef struct ItemCheckResolution { uint8_t item; uint8_t display_item; /* leave unset (0xFF/NONE) to use the item */ + bool was_resolved; } ItemCheckResolution; /* Return true and write out_result to replace the result, or false to leave it unchanged. */ diff --git a/src/d/actor/d_a_demo_item.cpp b/src/d/actor/d_a_demo_item.cpp index 1af403d2a6..0c092cf59b 100644 --- a/src/d/actor/d_a_demo_item.cpp +++ b/src/d/actor/d_a_demo_item.cpp @@ -462,7 +462,7 @@ int daDitem_c::create() { m_itemNo = daDitem_prm::getNo(this); #if TARGET_PC - const auto [item, displayItem] = dusk::mods::item_check_resolve(mItemGiveTag, m_itemNo, this); + const auto [item, displayItem, _] = dusk::mods::item_check_resolve(mItemGiveTag, m_itemNo, this); m_itemNo = item; setDisplayItemNo(displayItem); const char* arc_name = dItem_data::getArcName(displayItem); diff --git a/src/d/actor/d_a_obj_item.cpp b/src/d/actor/d_a_obj_item.cpp index e41529481d..e06eb37e50 100644 --- a/src/d/actor/d_a_obj_item.cpp +++ b/src/d/actor/d_a_obj_item.cpp @@ -268,7 +268,7 @@ int daItem_c::_daItem_create() { const u32 params = fopAcM_GetParam(this); mOriginalItemNo = params & 0xFF; mItemGiveTag = dusk::mods::item_give_tag_freestanding(daItem_prm::getItemBitNo(this)); - const auto [item, displayItem] = + const auto [item, displayItem, _] = dusk::mods::item_check_resolve(mItemGiveTag, mOriginalItemNo, this); mItemOverridden = item != mOriginalItemNo; setDisplayItemNo(displayItem); diff --git a/src/d/actor/d_a_obj_life_container.cpp b/src/d/actor/d_a_obj_life_container.cpp index 4f5cbbd9cb..783fd4698d 100644 --- a/src/d/actor/d_a_obj_life_container.cpp +++ b/src/d/actor/d_a_obj_life_container.cpp @@ -153,7 +153,7 @@ int daObjLife_c::create() { if (mItemGiveOriginalNo == dItemNo_NONE_e) { mOriginalItemNo = parameterItemNo; mItemGiveTag = dusk::mods::item_give_tag_freestanding(getSaveBitNo()); - const auto [item, displayItem] = + const auto [item, displayItem, _] = dusk::mods::item_check_resolve(mItemGiveTag, mOriginalItemNo, this); setDisplayItemNo(displayItem); mItemOverridden = item != mOriginalItemNo; @@ -163,7 +163,7 @@ int daObjLife_c::create() { } else if (mGoldenWolfItem) { mOriginalItemNo = mItemGiveOriginalNo; mItemGiveTag = dusk::mods::item_give_tag_golden_wolf(static_cast(field_0x938)); - const auto [item, displayItem] = + const auto [item, displayItem, _] = dusk::mods::item_check_resolve(mItemGiveTag, mOriginalItemNo, this); setDisplayItemNo(displayItem); mItemOverridden = item != mOriginalItemNo; diff --git a/src/d/actor/d_a_obj_master_sword.cpp b/src/d/actor/d_a_obj_master_sword.cpp index 36fa786808..a1ef6b1709 100644 --- a/src/d/actor/d_a_obj_master_sword.cpp +++ b/src/d/actor/d_a_obj_master_sword.cpp @@ -151,11 +151,7 @@ void daObjMasterSword_c::create_init() { int daObjMasterSword_c::create() { fopAcM_ct(this, daObjMasterSword_c); -#if TARGET_PC - if (dComIfGs_isEventBit(dSv_event_flag_c::F_0264)) { -#else if (dComIfGs_isEventBit(dSv_event_flag_c::saveBitLabels[getFlagNo()])) { -#endif return cPhs_ERROR_e; } @@ -199,7 +195,7 @@ int daObjMasterSword_c::execute() { #if TARGET_PC const auto masterSword = dusk::mods::item_check_commit( ITEM_CHECK_MASTER_SWORD, dItemNo_MASTER_SWORD_e, this); - if (masterSword.itemNo == dItemNo_MASTER_SWORD_e) { + if (!masterSword.was_resolved) { dComIfGs_onItemFirstBit(dItemNo_MASTER_SWORD_e); dMeter2Info_setSword(dItemNo_MASTER_SWORD_e, false); dComIfGs_setSelectEquipSword(dItemNo_MASTER_SWORD_e); @@ -214,7 +210,7 @@ int daObjMasterSword_c::execute() { const auto shadowCrystal = dusk::mods::item_check_commit( ITEM_CHECK_SHADOW_CRYSTAL, dItemNo_SHADOW_CRYSTAL_e, this); - if (shadowCrystal.itemNo == dItemNo_SHADOW_CRYSTAL_e) { + if (!shadowCrystal.was_resolved) { execItemGet(shadowCrystal.itemNo, shadowCrystal.tag, this); } else if (shadowCrystal.itemNo == dItemNo_NONE_e) { dusk::mods::item_check_complete(shadowCrystal, this); @@ -222,15 +218,14 @@ int daObjMasterSword_c::execute() { dusk::mods::item_check_enqueue(shadowCrystal, dusk::mods::ItemGiveMode::Demo); } - dComIfGs_onEventBit(dSv_event_flag_c::F_0264); #else dComIfGs_onItemFirstBit(dItemNo_MASTER_SWORD_e); dMeter2Info_setSword(dItemNo_MASTER_SWORD_e, false); dComIfGs_setSelectEquipSword(dItemNo_MASTER_SWORD_e); dComIfGp_setItemLifeCount(dComIfGs_getMaxLife(), 0); - dComIfGs_onEventBit(dSv_event_flag_c::saveBitLabels[getFlagNo()]); #endif + dComIfGs_onEventBit(dSv_event_flag_c::saveBitLabels[getFlagNo()]); fopAcM_delete(this); } diff --git a/src/d/actor/d_a_obj_smallkey.cpp b/src/d/actor/d_a_obj_smallkey.cpp index 6914cee5f0..1fd6025ce6 100644 --- a/src/d/actor/d_a_obj_smallkey.cpp +++ b/src/d/actor/d_a_obj_smallkey.cpp @@ -157,7 +157,7 @@ int daKey_c::create() { #if TARGET_PC mItemGiveTag = dusk::mods::item_give_tag_freestanding(getSaveBitNo()); - const auto [item, displayItem] = + const auto [item, displayItem, _] = dusk::mods::item_check_resolve(mItemGiveTag, dItemNo_SMALL_KEY_e, this); m_itemNo = item; if (m_itemNo == dItemNo_NONE_e) { diff --git a/src/d/actor/d_a_shop_item.cpp b/src/d/actor/d_a_shop_item.cpp index 304fd1b1da..edd16b9ecf 100644 --- a/src/d/actor/d_a_shop_item.cpp +++ b/src/d/actor/d_a_shop_item.cpp @@ -106,7 +106,7 @@ const char* daShopItem_c::getShopArcname() { if (m_itemNo != dItemNo_NONE_e && mItemGiveOriginalNo == dItemNo_NONE_e) { mItemGiveOriginalNo = m_itemNo; mItemGiveTag = dusk::mods::item_give_tag_shop(mItemGiveOriginalNo); - const auto [_, displayItem] = + const auto [_, displayItem, was_resolved] = dusk::mods::item_check_resolve(mItemGiveTag, mItemGiveOriginalNo, this); setDisplayItemNo(displayItem); mItemOverridden = displayItem != mItemGiveOriginalNo; diff --git a/src/dusk/mods/item.hpp b/src/dusk/mods/item.hpp index bda0d4f7ee..5b675ed64c 100644 --- a/src/dusk/mods/item.hpp +++ b/src/dusk/mods/item.hpp @@ -20,6 +20,7 @@ struct ItemCheckResult { uint32_t tag = 0; uint8_t itemNo = 0; uint8_t displayItemNo = 0; + bool was_resolved = false; }; ItemCheckResolution item_check_resolve(const char* name, uint8_t itemNo, fopAc_ac_c* giver); diff --git a/src/dusk/mods/item_checks.cpp b/src/dusk/mods/item_checks.cpp index df881e6211..0d2e5a4982 100644 --- a/src/dusk/mods/item_checks.cpp +++ b/src/dusk/mods/item_checks.cpp @@ -235,6 +235,7 @@ ItemCheckResolution item_check_resolve(const char* name, uint8_t itemNo, fopAc_a .vanilla_item = itemNo, .current_item = itemNo, .current_display_item = itemNo, + .was_resolved = false, }; for (const auto& resolve : resolves) { if (!resolve.mod->active) { @@ -243,6 +244,7 @@ ItemCheckResolution item_check_resolve(const char* name, uint8_t itemNo, fopAc_a if (resolve.fixedValue) { info.current_item = resolve.itemNo; info.current_display_item = resolve.itemNo; + info.was_resolved = true; continue; } @@ -257,6 +259,7 @@ ItemCheckResolution item_check_resolve(const char* name, uint8_t itemNo, fopAc_a } info.current_item = resolution.item; info.current_display_item = resolution.display_item; + info.was_resolved = true; } } catch (const std::exception& e) { fail_mod(*resolve.mod, MOD_ERROR, @@ -269,6 +272,7 @@ ItemCheckResolution item_check_resolve(const char* name, uint8_t itemNo, fopAc_a return { .item = info.current_item, .display_item = info.current_display_item, + .was_resolved = info.was_resolved, }; } diff --git a/src/dusk/mods/item_gives.cpp b/src/dusk/mods/item_gives.cpp index 5d75dcfc15..8feb0a7847 100644 --- a/src/dusk/mods/item_gives.cpp +++ b/src/dusk/mods/item_gives.cpp @@ -265,6 +265,7 @@ ItemCheckResult item_check_commit(uint32_t giveTag, uint8_t itemNo, fopAc_ac_c* .tag = giveTag, .itemNo = committed->resolution.item, .displayItemNo = committed->resolution.display_item, + .was_resolved = committed->resolution.was_resolved, }; } @@ -274,6 +275,7 @@ ItemCheckResult item_check_commit(uint32_t giveTag, uint8_t itemNo, fopAc_ac_c* .tag = giveTag, .itemNo = committed.resolution.item, .displayItemNo = committed.resolution.display_item, + .was_resolved = committed.resolution.was_resolved, }; }