update item service and fix master sword checks

This commit is contained in:
gymnast86
2026-08-28 22:08:25 -07:00
parent f0086952d2
commit f4163de0de
11 changed files with 42 additions and 22 deletions
+23 -7
View File
@@ -14,6 +14,7 @@
#include <mods/svc/log.hpp>
#include <mods/items.h>
#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<bool*>(retval) = doSkip;
}
void hookPostMasterSwordExecuteWait(ModContext*, void* args, void* retval, void*) {
auto objMasterSword = mods::arg<daObjMasterSword_c*>(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<dEvt_control_c__skipper>(svc_hook);
mods::hook::uninstall<daObjMasterSword_c__executeWait>(svc_hook);
return MOD_OK;
}
}
+3 -1
View File
@@ -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. */
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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);
+2 -2
View File
@@ -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<u16>(field_0x938));
const auto [item, displayItem] =
const auto [item, displayItem, _] =
dusk::mods::item_check_resolve(mItemGiveTag, mOriginalItemNo, this);
setDisplayItemNo(displayItem);
mItemOverridden = item != mOriginalItemNo;
+3 -8
View File
@@ -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);
}
+1 -1
View File
@@ -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) {
+1 -1
View File
@@ -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;
+1
View File
@@ -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);
+4
View File
@@ -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,
};
}
+2
View File
@@ -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,
};
}