mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-24 22:35:53 -04:00
Fix Golden Wolf item persistence
This commit is contained in:
@@ -92,6 +92,7 @@ public:
|
||||
u8 mOriginalItemNo;
|
||||
bool mItemOverridden;
|
||||
bool mOverrideHover;
|
||||
bool mGoldenWolfItem;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <mods/svc/hook.hpp>
|
||||
#include <mods/svc/log.hpp>
|
||||
#include <mods/items.h>
|
||||
|
||||
#include "c/c_damagereaction.h"
|
||||
#include "d/actor/d_a_alink.h"
|
||||
@@ -2812,17 +2813,33 @@ HookAction hookPreObjLifeCreate(ModContext*, void* args, void* retval, void*) {
|
||||
auto goldenWolfFlags = getCurrentGoldenWolfFlags(roomNo);
|
||||
// Don't spawn this item if we haven't howled at the howling stone, or if we've already
|
||||
// obtained the item
|
||||
if ((goldenWolfFlags.howledAtStoneFlag != 0xFFFF && !dComIfGs_isEventBit(goldenWolfFlags.howledAtStoneFlag)) ||
|
||||
dComIfGs_isEventBit(goldenWolfFlags.obtainedItemFlag))
|
||||
if (goldenWolfFlags.obtainedItemFlag == 0xFFFF ||
|
||||
(goldenWolfFlags.howledAtStoneFlag != 0xFFFF &&
|
||||
!dComIfGs_isEventBit(goldenWolfFlags.howledAtStoneFlag)) ||
|
||||
dComIfGs_isEventBit(goldenWolfFlags.obtainedItemFlag) ||
|
||||
!randomizer_GetContext().mGoldenWolfOverrides.contains(
|
||||
goldenWolfFlags.obtainedItemFlag))
|
||||
{
|
||||
*static_cast<int*>(retval) = cPhs_ERROR_e;
|
||||
return HOOK_SKIP_ORIGINAL;
|
||||
}
|
||||
|
||||
// Store the map marker flag and obtained item flags to turn off/on later if
|
||||
// the player collects the item
|
||||
// The actor moves these placement angles into field_0x938/field_0x93a during create.
|
||||
i_this->home.angle.z = goldenWolfFlags.mapMarkerFlag;
|
||||
i_this->home.angle.x = static_cast<s16>(goldenWolfFlags.obtainedItemFlag);
|
||||
|
||||
i_this->mItemGiveOriginalNo = itemId;
|
||||
i_this->mGoldenWolfItem = true;
|
||||
const std::string checkName =
|
||||
std::string{ITEM_CHECK_GOLDEN_WOLF_PREFIX} +
|
||||
std::to_string(goldenWolfFlags.obtainedItemFlag);
|
||||
if (session::svc_mng.item->resolve_check(session::svc_mng.mod_ctx, checkName.c_str(),
|
||||
itemId, &itemId) != MOD_OK)
|
||||
{
|
||||
*static_cast<int*>(retval) = cPhs_ERROR_e;
|
||||
return HOOK_SKIP_ORIGINAL;
|
||||
}
|
||||
fopAcM_SetParam(i_this, (params & 0xFFFFFF00) | itemId);
|
||||
}
|
||||
|
||||
// Also adjust the height of the object depending on the item
|
||||
@@ -2913,18 +2930,23 @@ HookAction hookPreObjLifeCreate(ModContext*, void* args, void* retval, void*) {
|
||||
return HOOK_CONTINUE;
|
||||
}
|
||||
|
||||
void hookPostObjLifeActionGetDemo(ModContext*, void* args, void*, void*) {
|
||||
HookAction hookPreObjLifeActionGetDemo(ModContext*, void* args, void*, void*) {
|
||||
auto* i_this = mods::arg<daObjLife_c*>(args, 0);
|
||||
|
||||
// In randomizer, turn off the map marker flag for this golden wolf replacement item
|
||||
// if we're collecting it. We store the map marker flag in unused home.angle.z
|
||||
// Also set the flag for having collected this golden wolf item, stored in home.angle.x
|
||||
if (static_cast<u16>(i_this->home.angle.z) != 0xFFFF) {
|
||||
dComIfGs_offSwitch(static_cast<u16>(i_this->home.angle.z), fopAcM_GetRoomNo(i_this));
|
||||
if (!i_this->mGoldenWolfItem || !dComIfGp_evmng_endCheck("DEFAULT_GETITEM"))
|
||||
{
|
||||
return HOOK_CONTINUE;
|
||||
}
|
||||
if (static_cast<u16>(i_this->home.angle.x) != 0xFFFF) {
|
||||
dComIfGs_onEventBit(static_cast<u16>(i_this->home.angle.x));
|
||||
|
||||
const u16 mapMarkerFlag = static_cast<u16>(i_this->field_0x93a);
|
||||
const u16 obtainedItemFlag = static_cast<u16>(i_this->field_0x938);
|
||||
if (mapMarkerFlag != 0xFFFF) {
|
||||
dComIfGs_offSwitch(mapMarkerFlag, fopAcM_GetRoomNo(i_this));
|
||||
}
|
||||
if (obtainedItemFlag != 0xFFFF) {
|
||||
dComIfGs_onEventBit(obtainedItemFlag);
|
||||
}
|
||||
return HOOK_CONTINUE;
|
||||
}
|
||||
|
||||
HookAction hookPreObjLifeCalcScale(ModContext*, void* args, void* retval, void*) {
|
||||
@@ -3231,7 +3253,7 @@ ModResult initialize() {
|
||||
|
||||
ADD_HOOK_PRE(daObjLife_c__setEffect, hookPreObjLifeSetEffect);
|
||||
ADD_HOOK_PRE(daObjLife_c__create, hookPreObjLifeCreate);
|
||||
ADD_HOOK_POST(daObjLife_c__actionGetDemo, hookPostObjLifeActionGetDemo);
|
||||
ADD_HOOK_PRE(daObjLife_c__actionGetDemo, hookPreObjLifeActionGetDemo);
|
||||
ADD_HOOK_PRE(daObjLife_c__calcScale, hookPreObjLifeCalcScale);
|
||||
|
||||
ADD_HOOK_POST(getCollectSmell, hookPostGetCollectSmell);
|
||||
|
||||
@@ -70,6 +70,19 @@ std::optional<DerivedKey> parse_derived(const char* name, std::string_view prefi
|
||||
return DerivedKey{stage_id, static_cast<u16>((stage_id << 8) | (n & 0xFF))};
|
||||
}
|
||||
|
||||
std::optional<u16> parse_flag_check(const char* name, std::string_view prefix) {
|
||||
if (std::strncmp(name, prefix.data(), prefix.size()) != 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
const char* value = name + prefix.size();
|
||||
char* end = nullptr;
|
||||
const unsigned long flag = std::strtoul(value, &end, 10);
|
||||
if (value == end || *end != '\0' || flag > 0xFFFF) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return static_cast<u16>(flag);
|
||||
}
|
||||
|
||||
template <typename Map>
|
||||
bool lookup_override(const Map& map, u16 key, uint8_t* out_item, bool progressive) {
|
||||
const auto it = map.find(key);
|
||||
@@ -102,6 +115,9 @@ bool resolve_check(ModContext*, const ItemCheckInfo* info, uint8_t* out_item, vo
|
||||
}
|
||||
return lookup_override(ctx.mFreestandingItemOverrides, key->key, out_item, true);
|
||||
}
|
||||
if (auto flag = parse_flag_check(info->name, ITEM_CHECK_GOLDEN_WOLF_PREFIX)) {
|
||||
return lookup_override(ctx.mGoldenWolfOverrides, *flag, out_item, true);
|
||||
}
|
||||
if (auto key = parse_derived(info->name, ITEM_CHECK_POE_PREFIX)) {
|
||||
return lookup_override(ctx.mPoeOverrides, key->key, out_item, true);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define ITEM_CHECK_BUG_PREFIX "bug:" /* <insect_item> */
|
||||
#define ITEM_CHECK_CHEST_PREFIX "chest:" /* <stage>:<box> */
|
||||
#define ITEM_CHECK_FREESTANDING_PREFIX "freestanding:" /* <stage>:<bit> */
|
||||
#define ITEM_CHECK_GOLDEN_WOLF_PREFIX "golden_wolf:" /* <event_flag> */
|
||||
#define ITEM_CHECK_POE_PREFIX "poe:" /* <stage>:<switch> */
|
||||
#define ITEM_CHECK_SHOP_PREFIX "shop:" /* <stage>:<item> */
|
||||
#define ITEM_CHECK_SKY_PREFIX "sky:" /* <stage>:<room> */
|
||||
|
||||
@@ -159,9 +159,19 @@ int daObjLife_c::create() {
|
||||
if (mItemOverridden) {
|
||||
fopAcM_SetParam(this, (params & 0xFFFFFF00) | resolvedItem);
|
||||
}
|
||||
} else if (mGoldenWolfItem) {
|
||||
mOriginalItemNo = mItemGiveOriginalNo;
|
||||
const u16 obtainedItemFlag = static_cast<u16>(field_0x938);
|
||||
const u8 resolvedItem =
|
||||
dusk::mods::item_check_golden_wolf(obtainedItemFlag, mOriginalItemNo, this);
|
||||
mItemGiveTag = dusk::mods::item_give_tag_golden_wolf(obtainedItemFlag);
|
||||
mItemOverridden = resolvedItem != mOriginalItemNo;
|
||||
if (resolvedItem != parameterItemNo) {
|
||||
fopAcM_SetParam(this, (params & 0xFFFFFF00) | resolvedItem);
|
||||
}
|
||||
} else {
|
||||
mOriginalItemNo = mItemGiveOriginalNo;
|
||||
mItemOverridden = parameterItemNo != mItemGiveOriginalNo;
|
||||
mItemOverridden = parameterItemNo != mOriginalItemNo;
|
||||
}
|
||||
mOverrideHover =
|
||||
mItemOverridden &&
|
||||
|
||||
@@ -25,12 +25,14 @@ ItemCheckResult item_check_commit(uint32_t giveTag, uint8_t itemNo, fopAc_ac_c*
|
||||
uint8_t item_check_chest(uint8_t boxNo, uint8_t itemNo, fopAc_ac_c* chest);
|
||||
uint8_t item_check_boss(uint8_t itemNo, fopAc_ac_c* boss);
|
||||
uint8_t item_check_freestanding(uint8_t bitNo, uint8_t itemNo, fopAc_ac_c* item);
|
||||
uint8_t item_check_golden_wolf(uint16_t eventFlag, uint8_t itemNo, fopAc_ac_c* item);
|
||||
uint8_t item_check_shop(uint8_t itemNo, fopAc_ac_c* giver);
|
||||
|
||||
uint32_t item_give_tag(const char* name);
|
||||
uint32_t item_give_tag_chest(uint8_t boxNo);
|
||||
uint32_t item_give_tag_boss();
|
||||
uint32_t item_give_tag_freestanding(uint8_t bitNo);
|
||||
uint32_t item_give_tag_golden_wolf(uint16_t eventFlag);
|
||||
uint32_t item_give_tag_poe(uint8_t bitNo);
|
||||
uint32_t item_give_tag_shop(uint8_t itemNo);
|
||||
uint32_t item_give_tag_bug(uint8_t insectId);
|
||||
|
||||
@@ -143,6 +143,10 @@ std::string freestanding_check_name(uint8_t bitNo) {
|
||||
return fmt::format("freestanding:{}:{}", current_stage_name(), bitNo);
|
||||
}
|
||||
|
||||
std::string golden_wolf_check_name(uint16_t eventFlag) {
|
||||
return fmt::format("golden_wolf:{}", eventFlag);
|
||||
}
|
||||
|
||||
std::string poe_check_name(uint8_t bitNo) {
|
||||
return fmt::format("poe:{}:{}", current_stage_name(), bitNo);
|
||||
}
|
||||
@@ -274,6 +278,14 @@ uint8_t item_check_freestanding(uint8_t bitNo, uint8_t itemNo, fopAc_ac_c* item)
|
||||
return item_check(name.c_str(), itemNo, item);
|
||||
}
|
||||
|
||||
uint8_t item_check_golden_wolf(uint16_t eventFlag, uint8_t itemNo, fopAc_ac_c* item) {
|
||||
if (s_modChecks.empty()) {
|
||||
return itemNo;
|
||||
}
|
||||
const auto name = golden_wolf_check_name(eventFlag);
|
||||
return item_check(name.c_str(), itemNo, item);
|
||||
}
|
||||
|
||||
uint8_t item_check_shop(uint8_t itemNo, fopAc_ac_c* giver) {
|
||||
if (s_modChecks.empty()) {
|
||||
return itemNo;
|
||||
@@ -314,6 +326,10 @@ uint32_t item_give_tag_freestanding(uint8_t bitNo) {
|
||||
return item_give_tag(freestanding_check_name(bitNo).c_str());
|
||||
}
|
||||
|
||||
uint32_t item_give_tag_golden_wolf(uint16_t eventFlag) {
|
||||
return item_give_tag(golden_wolf_check_name(eventFlag).c_str());
|
||||
}
|
||||
|
||||
uint32_t item_give_tag_poe(uint8_t bitNo) {
|
||||
return item_give_tag(poe_check_name(bitNo).c_str());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user