hook up item check overriding

This commit is contained in:
TakaRikka
2026-08-12 19:42:57 -07:00
parent 839d8fdb63
commit 11055282ff
8 changed files with 1772 additions and 24 deletions
+118 -5
View File
@@ -7,6 +7,8 @@
#include "item_ids.h"
#include "tools.h"
#include "stages.h"
#include "item.hpp"
#include "verify_item_functions.h"
#include "d/d_com_inf_game.h"
#include "d/d_item.h"
@@ -21,7 +23,118 @@ ModResult initialize(const ServiceManager& services) {
return MOD_OK;
}
ItemCheckHandle s_check_resolver{};
ItemGiveHandle s_check_observer{};
struct DerivedKey {
int stage_id;
u16 key;
};
std::optional<DerivedKey> parse_derived(const char* name, std::string_view prefix) {
if (std::strncmp(name, prefix.data(), prefix.size()) != 0) {
return std::nullopt;
}
const char* stage_begin = name + prefix.size();
const char* stage_end = std::strchr(stage_begin, ':');
if (stage_end == nullptr) {
return std::nullopt;
}
const std::string stage{stage_begin, stage_end};
const int stage_id = getStageID(stage.c_str());
if (stage_id < 0) {
return std::nullopt;
}
const int n = std::atoi(stage_end + 1);
return DerivedKey{stage_id, static_cast<u16>((stage_id << 8) | (n & 0xFF))};
}
template <typename Map>
bool lookup_override(const Map& map, u16 key, uint8_t* out_item, bool progressive) {
const auto it = map.find(key);
if (it == map.end()) {
return false;
}
*out_item = progressive ? static_cast<uint8_t>(verifyProgressiveItem(it->second)) : it->second;
return true;
}
bool resolve_check(ModContext*, const ItemCheckInfo* info, uint8_t* out_item, void*) {
auto& ctx = randomizer_GetContext();
if (auto it = ctx.mItemLocations.find(info->name); it != ctx.mItemLocations.end()) {
*out_item = static_cast<uint8_t>(it->second.itemId);
return true;
}
if (auto key = parse_derived(info->name, "chest:")) {
return lookup_override(ctx.mTreasureChestOverrides, key->key, out_item, false);
}
if (auto key = parse_derived(info->name, "freestanding:")) {
if (key->stage_id == Ook) {
if (auto it = ctx.mItemLocations.find("Forest Temple Gale Boomerang");
it != ctx.mItemLocations.end()) {
*out_item = static_cast<uint8_t>(verifyProgressiveItem(it->second.itemId));
return true;
}
return false;
}
return lookup_override(ctx.mFreestandingItemOverrides, key->key, out_item, true);
}
if (auto key = parse_derived(info->name, "poe:")) {
return lookup_override(ctx.mPoeOverrides, key->key, out_item, false);
}
if (auto key = parse_derived(info->name, "shop:")) {
return lookup_override(ctx.mShopOverrides, key->key, out_item, true);
}
if (auto key = parse_derived(info->name, "sky:")) {
return lookup_override(ctx.mSkyCharacterOverrides, key->key, out_item, true);
}
if (std::strncmp(info->name, "bug:", 4) == 0) {
const u8 insect = static_cast<u8>(std::atoi(info->name + 4));
if (auto it = ctx.mBugRewardOverrides.find(insect); it != ctx.mBugRewardOverrides.end()) {
*out_item = static_cast<uint8_t>(verifyProgressiveItem(it->second));
return true;
}
return false;
}
return false;
}
void observe_give(ModContext*, const ItemGiveInfo* info, void*) {
if (info->check_name == nullptr) {
return;
}
auto& ctx = randomizer_GetContext();
if (ctx.mItemLocations.contains(info->check_name)) {
randomizer_setTempFlagForLocation(info->check_name);
}
if (std::strcmp(info->check_name, "Arbiters Grounds Dungeon Reward") == 0) {
dComIfGs_onItem(0x9E, -1);
} else if (auto key = parse_derived(info->check_name, "freestanding:");
key && key->stage_id == Ook)
{
dComIfGs_onItem(0x9D, -1);
randomizer_setTempFlagForLocation("Forest Temple Gale Boomerang");
}
}
void activateSeed() {
auto& ctx = randomizer_GetContext();
item::apply_item_data_tables();
svc_mng.item->set_check_resolver(mod_ctx, nullptr, resolve_check, nullptr, &s_check_resolver);
svc_mng.item->observe_gives(mod_ctx, observe_give, nullptr, &s_check_observer);
}
void setupRandomizerFile() {
activateSeed();
// Setup file based on randomizer data
auto& randoData = randomizer_GetContext();
randoData.mCreatingSave = true;
@@ -46,22 +159,22 @@ void setupRandomizerFile() {
{
dComIfGs_onDarkClearLV(0);
dComIfGs_setLightDropNum(0, 0x10);
execItemGet(dItemNo_Randomizer_DROP_CONTAINER_e);
execItemGet(dItemNo_Randomizer_WEAR_KOKIRI_e);
item::exec_item_get(dItemNo_Randomizer_DROP_CONTAINER_e);
item::exec_item_get(dItemNo_Randomizer_WEAR_KOKIRI_e);
}
if (dComIfGs_isEventBit(CLEARED_ELDIN_TWILIGHT))
{
dComIfGs_onDarkClearLV(1);
dComIfGs_setLightDropNum(1, 0x10);
execItemGet(dItemNo_Randomizer_DROP_CONTAINER02_e);
item::exec_item_get(dItemNo_Randomizer_DROP_CONTAINER02_e);
}
if (dComIfGs_isEventBit(CLEARED_LANAYRU_TWILIGHT))
{
dComIfGs_onDarkClearLV(2);
dComIfGs_setLightDropNum(2, 0x10);
execItemGet(dItemNo_Randomizer_DROP_CONTAINER03_e);
item::exec_item_get(dItemNo_Randomizer_DROP_CONTAINER03_e);
}
if (randoData.mSettings[RandomizerContext::SKIP_MINOR_CUTSCENES] == RandomizerContext::ON)
@@ -90,7 +203,7 @@ void setupRandomizerFile() {
// Set starting inventory
for (const auto& itemId: randoData.mStartingInventory) {
execItemGet(itemId);
item::exec_item_get(itemId);
}
g_randomizerState = RandomizerState();