From 73052617eda789f957040f98d9368d9cf453a123 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Sun, 12 Mar 2023 00:00:03 -0700 Subject: [PATCH] [GI] Item_Give and OnReceiveItem updates (#2580) * Changed OnReceiveItem hook to pass GetItemEntry, which required the following changes: Reworked the references to it in `z_parameter` to call a single function with the item return and hook call in it for ease of editing. Modified the pendingSale functionality to set and pass a modIndex value as well, as mod items (like randomizer) in shops still use the vanilla sale path. * Missed some files for the pendingSale changes. Also added Randomizer_Item_Give to the OnReceiveItem system. * Ice traps now trigger OnReceiveItem. * All ice traps truly do work now. As a side effect, item autosave doesn't work for shop/scrub/merchant transactions, requires new OnSaleEnded hook that can also call the autosave. * Removed unnecessary calls to ItemTable_RetrieveEntry where GetItemEntry properties were being used to call it. General code cleanup. * Added OnSaleEnd hook for when rupees are finished deducting after a sale. Migrated AutoSave to its own function, registered AutoSave function to OnReceiveItem and OnSaleEnd hooks to help with autsaving after buying items. Some futureproofing for AutoSave function with parameters for skipping autosave, for when transition end is migrated to AutoSave function (whether through direct call or through a hook). * Renamed hook paramaters, and registered hook function parameters, to a more descriptive alternative. * Missed a couple, fixed a typo. * One more missed paramater name refactor. Refactored all references to OnReceiveItem to OnItemReceive to mirror upcoming full hook refactor for name ordering conventions. Up-to-date with develop. --- soh/include/z64save.h | 1 + .../game-interactor/GameInteractor.h | 4 +- .../game-interactor/GameInteractor_Hooks.cpp | 8 +- .../game-interactor/GameInteractor_Hooks.h | 3 +- soh/soh/Enhancements/mods.cpp | 120 ++++----- soh/soh/SaveManager.cpp | 1 + soh/src/code/z_parameter.c | 232 +++++++----------- soh/src/code/z_sram.c | 2 + soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c | 5 +- soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c | 4 +- .../overlays/actors/ovl_En_GirlA/z_en_girla.c | 86 +++++-- soh/src/overlays/actors/ovl_En_Js/z_en_js.c | 5 +- soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c | 5 +- .../overlays/actors/ovl_En_Ossan/z_en_ossan.c | 1 + soh/src/overlays/actors/ovl_En_Si/z_en_si.c | 2 + soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c | 4 +- .../actors/ovl_player_actor/z_player.c | 4 + 17 files changed, 256 insertions(+), 231 deletions(-) diff --git a/soh/include/z64save.h b/soh/include/z64save.h index d44a703df..435a97a7b 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -251,6 +251,7 @@ typedef struct { /* 0x1422 */ s16 sunsSongState; // controls the effects of suns song /* 0x1424 */ s16 healthAccumulator; /* 0x1426 */ u16 pendingSale; + /* 0x1428 */ u16 pendingSaleMod; // #region SOH [General] // Upstream TODO: Move these to their own struct or name to more obviously specific to SoH /* */ uint32_t isMasterQuest; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 81a42d702..f60063dbd 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -4,6 +4,7 @@ #define GameInteractor_h #include "GameInteractionEffect.h" +#include "soh/Enhancements/item-tables/ItemTableTypes.h" typedef enum { /* 0x00 */ GI_LINK_SIZE_NORMAL, @@ -86,7 +87,8 @@ public: DEFINE_HOOK(OnLoadGame, void(int32_t fileNum)); DEFINE_HOOK(OnExitGame, void(int32_t fileNum)); DEFINE_HOOK(OnGameFrameUpdate, void()); - DEFINE_HOOK(OnReceiveItem, void(uint8_t item)); + DEFINE_HOOK(OnItemReceive, void(GetItemEntry itemEntry)); + DEFINE_HOOK(OnSaleEnd, void(GetItemEntry itemEntry)); DEFINE_HOOK(OnSceneInit, void(int16_t sceneNum)); DEFINE_HOOK(OnPlayerUpdate, void()); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp index 4d65a0435..f1daa659a 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp @@ -14,8 +14,12 @@ void GameInteractor_ExecuteOnGameFrameUpdate() { GameInteractor::Instance->ExecuteHooks(); } -void GameInteractor_ExecuteOnReceiveItemHooks(uint8_t item) { - GameInteractor::Instance->ExecuteHooks(item); +void GameInteractor_ExecuteOnItemReceiveHooks(GetItemEntry itemEntry) { + GameInteractor::Instance->ExecuteHooks(itemEntry); +} + +void GameInteractor_ExecuteOnSaleEndHooks(GetItemEntry itemEntry) { + GameInteractor::Instance->ExecuteHooks(itemEntry); } void GameInteractor_ExecuteOnSceneInitHooks(int16_t sceneNum) { diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h index 2574306ab..51d8ecce4 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h @@ -4,7 +4,8 @@ extern "C" void GameInteractor_ExecuteOnLoadGame(int32_t fileNum); extern "C" void GameInteractor_ExecuteOnExitGame(int32_t fileNum); extern "C" void GameInteractor_ExecuteOnGameFrameUpdate(); -extern "C" void GameInteractor_ExecuteOnReceiveItemHooks(uint8_t item); +extern "C" void GameInteractor_ExecuteOnItemReceiveHooks(GetItemEntry itemEntry); +extern "C" void GameInteractor_ExecuteOnSaleEndHooks(GetItemEntry itemEntry); extern "C" void GameInteractor_ExecuteOnSceneInit(int16_t sceneNum); extern "C" void GameInteractor_ExecuteOnPlayerUpdate(); diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 5e6a1c433..16d72539b 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -172,66 +172,74 @@ void RegisterSwitchAge() { }); } -void RegisterAutoSave() { - GameInteractor::Instance->RegisterGameHook([](u8 item) { - // Don't autosave immediately after buying items from shops to prevent getting them for free! - // Don't autosave in the Chamber of Sages since resuming from that map breaks the game - // Don't autosave during the Ganon fight when picking up the Master Sword - if ((CVarGetInteger("gAutosave", 0) > 0) && (gPlayState != NULL) && (gSaveContext.pendingSale == ITEM_NONE) && - (gPlayState->sceneNum != SCENE_KENJYANOMA) && (gPlayState->sceneNum != SCENE_GANON_DEMO)) { - if ((CVarGetInteger("gAutosave", 0) == 2) || (CVarGetInteger("gAutosave", 0) == 5)) { - // Autosave for all items - Play_PerformSave(gPlayState); +void AutoSave(GetItemEntry itemEntry) { + u8 item = itemEntry.itemId; + // Don't autosave immediately after buying items from shops to prevent getting them for free! + // Don't autosave in the Chamber of Sages since resuming from that map breaks the game + // Don't autosave during the Ganon fight when picking up the Master Sword + // Don't autosave in grottos since resuming from grottos breaks the game. + if ((CVarGetInteger("gAutosave", 0) > 0) && (gPlayState != NULL) && (gSaveContext.pendingSale == ITEM_NONE) && + (gPlayState->sceneNum != SCENE_YOUSEI_IZUMI_TATE) && (gPlayState->sceneNum != SCENE_KAKUSIANA) && + (gPlayState->sceneNum != SCENE_KENJYANOMA) && (gPlayState->sceneNum != SCENE_GANON_DEMO) && + (gPlayState->gameplayFrames > 60 && gSaveContext.cutsceneIndex < 0xFFF0)) { + if ((CVarGetInteger("gAutosave", 0) == 2) || (CVarGetInteger("gAutosave", 0) == 5) && (item != ITEM_NONE)) { + // Autosave for all items + Play_PerformSave(gPlayState); - } else if ((CVarGetInteger("gAutosave", 0) == 1) || (CVarGetInteger("gAutosave", 0) == 4)) { - // Autosave for major items - switch (item) { - case ITEM_STICK: - case ITEM_NUT: - case ITEM_BOMB: - case ITEM_BOW: - case ITEM_SEEDS: - case ITEM_FISHING_POLE: - case ITEM_MAGIC_SMALL: - case ITEM_MAGIC_LARGE: - case ITEM_INVALID_4: - case ITEM_INVALID_5: - case ITEM_INVALID_6: - case ITEM_INVALID_7: - case ITEM_HEART: - case ITEM_RUPEE_GREEN: - case ITEM_RUPEE_BLUE: - case ITEM_RUPEE_RED: - case ITEM_RUPEE_PURPLE: - case ITEM_RUPEE_GOLD: - case ITEM_INVALID_8: - case ITEM_STICKS_5: - case ITEM_STICKS_10: - case ITEM_NUTS_5: - case ITEM_NUTS_10: - case ITEM_BOMBS_5: - case ITEM_BOMBS_10: - case ITEM_BOMBS_20: - case ITEM_BOMBS_30: - case ITEM_ARROWS_SMALL: - case ITEM_ARROWS_MEDIUM: - case ITEM_ARROWS_LARGE: - case ITEM_SEEDS_30: - break; - case ITEM_BOMBCHU: - case ITEM_BOMBCHUS_5: - case ITEM_BOMBCHUS_20: - if (!CVarGetInteger("gBombchuDrops", 0)) { - Play_PerformSave(gPlayState); - } - break; - default: + } else if ((CVarGetInteger("gAutosave", 0) == 1) || (CVarGetInteger("gAutosave", 0) == 4) && (item != ITEM_NONE)) { + // Autosave for major items + switch (item) { + case ITEM_STICK: + case ITEM_NUT: + case ITEM_BOMB: + case ITEM_BOW: + case ITEM_SEEDS: + case ITEM_FISHING_POLE: + case ITEM_MAGIC_SMALL: + case ITEM_MAGIC_LARGE: + case ITEM_INVALID_4: + case ITEM_INVALID_5: + case ITEM_INVALID_6: + case ITEM_INVALID_7: + case ITEM_HEART: + case ITEM_RUPEE_GREEN: + case ITEM_RUPEE_BLUE: + case ITEM_RUPEE_RED: + case ITEM_RUPEE_PURPLE: + case ITEM_RUPEE_GOLD: + case ITEM_INVALID_8: + case ITEM_STICKS_5: + case ITEM_STICKS_10: + case ITEM_NUTS_5: + case ITEM_NUTS_10: + case ITEM_BOMBS_5: + case ITEM_BOMBS_10: + case ITEM_BOMBS_20: + case ITEM_BOMBS_30: + case ITEM_ARROWS_SMALL: + case ITEM_ARROWS_MEDIUM: + case ITEM_ARROWS_LARGE: + case ITEM_SEEDS_30: + case ITEM_NONE: + break; + case ITEM_BOMBCHU: + case ITEM_BOMBCHUS_5: + case ITEM_BOMBCHUS_20: + if (!CVarGetInteger("gBombchuDrops", 0)) { Play_PerformSave(gPlayState); - break; - } + } + break; + default: + Play_PerformSave(gPlayState); + break; } } - }); + } +} + +void RegisterAutoSave() { + GameInteractor::Instance->RegisterGameHook([](GetItemEntry itemEntry) { AutoSave(itemEntry); }); + GameInteractor::Instance->RegisterGameHook([](GetItemEntry itemEntry) { AutoSave(itemEntry); }); } void RegisterRupeeDash() { diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 270bca60c..7b0077788 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -571,6 +571,7 @@ void SaveManager::InitFileNormal() { gSaveContext.infTable[29] = 1; gSaveContext.sceneFlags[5].swch = 0x40000000; gSaveContext.pendingSale = ITEM_NONE; + gSaveContext.pendingSaleMod = MOD_NONE; strncpy(gSaveContext.sohStats.buildVersion, (const char*) gBuildVersion, sizeof(gSaveContext.sohStats.buildVersion) - 1); gSaveContext.sohStats.buildVersion[sizeof(gSaveContext.sohStats.buildVersion) - 1] = 0; diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 06d23c151..2a9fd13eb 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1698,6 +1698,16 @@ void Randomizer_GameplayStats_SetTimestamp(uint16_t item) { } } +u8 Return_Item_Entry(GetItemEntry itemEntry, ItemID returnItem ) { + GameInteractor_ExecuteOnItemReceiveHooks(itemEntry); + return returnItem; +} + +// Processes Item_Give returns +u8 Return_Item(u8 item, ModIndex modId, ItemID returnItem) { + return Return_Item_Entry(ItemTable_RetrieveEntry(modId, item), returnItem); +} + /** * @brief Adds the given item to Link's inventory. * @@ -1715,6 +1725,8 @@ u8 Item_Give(PlayState* play, u8 item) { s16 slot; s16 temp; + GetItemID returnItem = ITEM_NONE; + // Gameplay stats: Update the time the item was obtained GameplayStats_SetTimestamp(play, item); @@ -1738,8 +1750,7 @@ u8 Item_Give(PlayState* play, u8 item) { func_8006D0AC(play); } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item >= ITEM_SONG_MINUET) && (item <= ITEM_SONG_STORMS)) { gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_SONG_MINUET + QUEST_SONG_MINUET]; @@ -1750,8 +1761,7 @@ u8 Item_Give(PlayState* play, u8 item) { gBitFlags[item - ITEM_SONG_MINUET + QUEST_SONG_MINUET], gBitFlags[item - ITEM_SONG_MINUET]); osSyncPrintf(VT_RST); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item >= ITEM_KOKIRI_EMERALD) && (item <= ITEM_ZORA_SAPPHIRE)) { gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_KOKIRI_EMERALD + QUEST_KOKIRI_EMERALD]; @@ -1759,8 +1769,7 @@ u8 Item_Give(PlayState* play, u8 item) { osSyncPrintf("精霊石 = %x\n", gSaveContext.inventory.questItems); // "Spiritual Stones = %x" osSyncPrintf(VT_RST); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item == ITEM_STONE_OF_AGONY) || (item == ITEM_GERUDO_CARD)) { gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_STONE_OF_AGONY + QUEST_STONE_OF_AGONY]; @@ -1768,8 +1777,7 @@ u8 Item_Give(PlayState* play, u8 item) { osSyncPrintf("アイテム = %x\n", gSaveContext.inventory.questItems); // "Items = %x" osSyncPrintf(VT_RST); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_SKULL_TOKEN) { gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_SKULL_TOKEN + QUEST_SKULL_TOKEN]; gSaveContext.inventory.gsTokens++; @@ -1779,8 +1787,7 @@ u8 Item_Give(PlayState* play, u8 item) { osSyncPrintf("Nコイン = %x(%d)\n", gSaveContext.inventory.questItems, gSaveContext.inventory.gsTokens); osSyncPrintf(VT_RST); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item >= ITEM_SWORD_KOKIRI) && (item <= ITEM_SWORD_BGS)) { gSaveContext.inventory.equipment |= gBitFlags[item - ITEM_SWORD_KOKIRI] << gEquipShifts[EQUIP_SWORD]; @@ -1811,20 +1818,16 @@ u8 Item_Give(PlayState* play, u8 item) { } } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item >= ITEM_SHIELD_DEKU) && (item <= ITEM_SHIELD_MIRROR)) { gSaveContext.inventory.equipment |= (gBitFlags[item - ITEM_SHIELD_DEKU] << gEquipShifts[EQUIP_SHIELD]); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item >= ITEM_TUNIC_KOKIRI) && (item <= ITEM_TUNIC_ZORA)) { gSaveContext.inventory.equipment |= (gBitFlags[item - ITEM_TUNIC_KOKIRI] << gEquipShifts[EQUIP_TUNIC]); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item >= ITEM_BOOTS_KOKIRI) && (item <= ITEM_BOOTS_HOVER)) { gSaveContext.inventory.equipment |= (gBitFlags[item - ITEM_BOOTS_KOKIRI] << gEquipShifts[EQUIP_BOOTS]); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) { // Boss Key, Compass, and Dungeon Map exceptions for rando. // Rando should never be able to get here for Link's Pocket unless something goes wrong, @@ -1840,8 +1843,7 @@ u8 Item_Give(PlayState* play, u8 item) { } else { gSaveContext.inventory.dungeonItems[gSaveContext.mapIndex] |= gBitFlags[item - ITEM_KEY_BOSS]; } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_KEY_SMALL) { // Small key exceptions for rando with keysanity off. // Rando should never be able to get here for Link's Pocket unless something goes wrong, @@ -1851,45 +1853,35 @@ u8 Item_Give(PlayState* play, u8 item) { gSaveContext.sohStats.dungeonKeys[13]++; if (gSaveContext.inventory.dungeonKeys[13] < 0) { gSaveContext.inventory.dungeonKeys[13] = 1; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; } else { gSaveContext.inventory.dungeonKeys[13]++; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; } + return Return_Item(item, MOD_NONE, ITEM_NONE); } if (play->sceneNum == 92) { // Desert Colossus -> Spirit Temple. gSaveContext.sohStats.dungeonKeys[6]++; if (gSaveContext.inventory.dungeonKeys[6] < 0) { gSaveContext.inventory.dungeonKeys[6] = 1; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; } else { gSaveContext.inventory.dungeonKeys[6]++; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; } + return Return_Item(item, MOD_NONE, ITEM_NONE); } } gSaveContext.sohStats.dungeonKeys[gSaveContext.mapIndex]++; if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] < 0) { gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] = 1; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; } else { gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]++; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; } + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item == ITEM_QUIVER_30) || (item == ITEM_BOW)) { if (CUR_UPG_VALUE(UPG_QUIVER) == 0) { Inventory_ChangeUpgrade(UPG_QUIVER, 1); INV_CONTENT(ITEM_BOW) = ITEM_BOW; AMMO(ITEM_BOW) = CAPACITY(UPG_QUIVER, 1); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else { AMMO(ITEM_BOW)++; if (AMMO(ITEM_BOW) > CUR_CAPACITY(UPG_QUIVER)) { @@ -1899,30 +1891,25 @@ u8 Item_Give(PlayState* play, u8 item) { } else if (item == ITEM_QUIVER_40) { Inventory_ChangeUpgrade(UPG_QUIVER, 2); AMMO(ITEM_BOW) = CAPACITY(UPG_QUIVER, 2); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_QUIVER_50) { Inventory_ChangeUpgrade(UPG_QUIVER, 3); AMMO(ITEM_BOW) = CAPACITY(UPG_QUIVER, 3); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_BULLET_BAG_40) { Inventory_ChangeUpgrade(UPG_BULLET_BAG, 2); AMMO(ITEM_SLINGSHOT) = CAPACITY(UPG_BULLET_BAG, 2); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_BULLET_BAG_50) { Inventory_ChangeUpgrade(UPG_BULLET_BAG, 3); AMMO(ITEM_SLINGSHOT) = CAPACITY(UPG_BULLET_BAG, 3); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_BOMB_BAG_20) { if (CUR_UPG_VALUE(UPG_BOMB_BAG) == 0) { Inventory_ChangeUpgrade(UPG_BOMB_BAG, 1); INV_CONTENT(ITEM_BOMB) = ITEM_BOMB; AMMO(ITEM_BOMB) = CAPACITY(UPG_BOMB_BAG, 1); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else { AMMO(ITEM_BOMB)++; if (AMMO(ITEM_BOMB) > CUR_CAPACITY(UPG_BOMB_BAG)) { @@ -1932,79 +1919,66 @@ u8 Item_Give(PlayState* play, u8 item) { } else if (item == ITEM_BOMB_BAG_30) { Inventory_ChangeUpgrade(UPG_BOMB_BAG, 2); AMMO(ITEM_BOMB) = CAPACITY(UPG_BOMB_BAG, 2); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_BOMB_BAG_40) { Inventory_ChangeUpgrade(UPG_BOMB_BAG, 3); AMMO(ITEM_BOMB) = CAPACITY(UPG_BOMB_BAG, 3); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_BRACELET) { Inventory_ChangeUpgrade(UPG_STRENGTH, 1); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_GAUNTLETS_SILVER) { Inventory_ChangeUpgrade(UPG_STRENGTH, 2); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_GAUNTLETS_GOLD) { Inventory_ChangeUpgrade(UPG_STRENGTH, 3); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_SCALE_SILVER) { Inventory_ChangeUpgrade(UPG_SCALE, 1); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_SCALE_GOLDEN) { Inventory_ChangeUpgrade(UPG_SCALE, 2); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_WALLET_ADULT) { Inventory_ChangeUpgrade(UPG_WALLET, 1); if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_FULL_WALLETS)) { Rupees_ChangeBy(200); } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_WALLET_GIANT) { Inventory_ChangeUpgrade(UPG_WALLET, 2); if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_FULL_WALLETS)) { Rupees_ChangeBy(500); } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_STICK_UPGRADE_20) { if (gSaveContext.inventory.items[slot] == ITEM_NONE) { INV_CONTENT(ITEM_STICK) = ITEM_STICK; } Inventory_ChangeUpgrade(UPG_STICKS, 2); AMMO(ITEM_STICK) = CAPACITY(UPG_STICKS, 2); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_STICK_UPGRADE_30) { if (gSaveContext.inventory.items[slot] == ITEM_NONE) { INV_CONTENT(ITEM_STICK) = ITEM_STICK; } Inventory_ChangeUpgrade(UPG_STICKS, 3); AMMO(ITEM_STICK) = CAPACITY(UPG_STICKS, 3); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_NUT_UPGRADE_30) { if (gSaveContext.inventory.items[slot] == ITEM_NONE) { INV_CONTENT(ITEM_NUT) = ITEM_NUT; } Inventory_ChangeUpgrade(UPG_NUTS, 2); AMMO(ITEM_NUT) = CAPACITY(UPG_NUTS, 2); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_NUT_UPGRADE_40) { if (gSaveContext.inventory.items[slot] == ITEM_NONE) { INV_CONTENT(ITEM_NUT) = ITEM_NUT; } Inventory_ChangeUpgrade(UPG_NUTS, 3); AMMO(ITEM_NUT) = CAPACITY(UPG_NUTS, 3); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_LONGSHOT) { INV_CONTENT(item) = item; // always update "equips" as this is what is currently on the c-buttons @@ -2037,8 +2011,7 @@ u8 Item_Give(PlayState* play, u8 item) { } } } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_STICK) { if (gSaveContext.inventory.items[slot] == ITEM_NONE) { Inventory_ChangeUpgrade(UPG_STICKS, 1); @@ -2090,42 +2063,34 @@ u8 Item_Give(PlayState* play, u8 item) { if ((AMMO(ITEM_BOMB) += 1) > CUR_CAPACITY(UPG_BOMB_BAG)) { AMMO(ITEM_BOMB) = CUR_CAPACITY(UPG_BOMB_BAG); } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item >= ITEM_BOMBS_5) && (item <= ITEM_BOMBS_30)) { if ((AMMO(ITEM_BOMB) += sAmmoRefillCounts[item - ITEM_BOMBS_5]) > CUR_CAPACITY(UPG_BOMB_BAG)) { AMMO(ITEM_BOMB) = CUR_CAPACITY(UPG_BOMB_BAG); } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_BOMBCHU) { if (gSaveContext.inventory.items[slot] == ITEM_NONE) { INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU; AMMO(ITEM_BOMBCHU) = 10; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; } else { AMMO(ITEM_BOMBCHU) += 10; if (AMMO(ITEM_BOMBCHU) > 50) { AMMO(ITEM_BOMBCHU) = 50; } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; } + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item == ITEM_BOMBCHUS_5) || (item == ITEM_BOMBCHUS_20)) { if (gSaveContext.inventory.items[slot] == ITEM_NONE) { INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU; AMMO(ITEM_BOMBCHU) += sAmmoRefillCounts[item - ITEM_BOMBCHUS_5 + 8]; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; } else { AMMO(ITEM_BOMBCHU) += sAmmoRefillCounts[item - ITEM_BOMBCHUS_5 + 8]; if (AMMO(ITEM_BOMBCHU) > 50) { AMMO(ITEM_BOMBCHU) = 50; } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; } + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item >= ITEM_ARROWS_SMALL) && (item <= ITEM_ARROWS_LARGE)) { AMMO(ITEM_BOW) += sAmmoRefillCounts[item - ITEM_ARROWS_SMALL + 4]; @@ -2135,14 +2100,12 @@ u8 Item_Give(PlayState* play, u8 item) { osSyncPrintf("%d本 Item_MaxGet=%d\n", AMMO(ITEM_BOW), CUR_CAPACITY(UPG_QUIVER)); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_BOW; + return Return_Item(item, MOD_NONE, ITEM_BOW); } else if (item == ITEM_SLINGSHOT) { Inventory_ChangeUpgrade(UPG_BULLET_BAG, 1); INV_CONTENT(ITEM_SLINGSHOT) = ITEM_SLINGSHOT; AMMO(ITEM_SLINGSHOT) = 30; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_SEEDS) { AMMO(ITEM_SLINGSHOT) += 5; @@ -2152,12 +2115,10 @@ u8 Item_Give(PlayState* play, u8 item) { if (!(gSaveContext.itemGetInf[1] & 8)) { gSaveContext.itemGetInf[1] |= 8; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_SEEDS; + return Return_Item(item, MOD_NONE, ITEM_SEEDS); } else if (item == ITEM_SEEDS_30) { AMMO(ITEM_SLINGSHOT) += 30; @@ -2167,16 +2128,13 @@ u8 Item_Give(PlayState* play, u8 item) { if (!(gSaveContext.itemGetInf[1] & 8)) { gSaveContext.itemGetInf[1] |= 8; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_SEEDS; + return Return_Item(item, MOD_NONE, ITEM_SEEDS); } else if (item == ITEM_OCARINA_FAIRY) { INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_OCARINA_TIME) { INV_CONTENT(ITEM_OCARINA_TIME) = ITEM_OCARINA_TIME; // always update "equips" as this is what is currently on the c-buttons @@ -2208,8 +2166,7 @@ u8 Item_Give(PlayState* play, u8 item) { } } } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_BEAN) { if (gSaveContext.inventory.items[slot] == ITEM_NONE) { INV_CONTENT(item) = item; @@ -2219,26 +2176,22 @@ u8 Item_Give(PlayState* play, u8 item) { AMMO(ITEM_BEAN)++; BEANS_BOUGHT++; } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item == ITEM_HEART_PIECE_2) || (item == ITEM_HEART_PIECE)) { gSaveContext.inventory.questItems += 1 << (QUEST_HEART_PIECE + 4); gSaveContext.sohStats.heartPieces++; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_HEART_CONTAINER) { gSaveContext.healthCapacity += 0x10; gSaveContext.health += 0x10; gSaveContext.sohStats.heartContainers++; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_HEART) { osSyncPrintf("回復ハート回復ハート回復ハート\n"); // "Recovery Heart" if (play != NULL) { Health_ChangeBy(play, 0x10); } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return item; + return Return_Item(item, MOD_NONE, item); } else if (item == ITEM_MAGIC_SMALL) { if (gSaveContext.magicState != 10) { if (play != NULL) { @@ -2252,12 +2205,10 @@ u8 Item_Give(PlayState* play, u8 item) { if (!(gSaveContext.infTable[25] & 0x100)) { gSaveContext.infTable[25] |= 0x100; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return item; + return Return_Item(item, MOD_NONE, item); } else if (item == ITEM_MAGIC_LARGE) { if (gSaveContext.magicState != 10) { if (play != NULL) { @@ -2270,24 +2221,20 @@ u8 Item_Give(PlayState* play, u8 item) { if (!(gSaveContext.infTable[25] & 0x100)) { gSaveContext.infTable[25] |= 0x100; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return item; + return Return_Item(item, MOD_NONE, item); } else if ((item >= ITEM_RUPEE_GREEN) && (item <= ITEM_INVALID_8)) { Rupees_ChangeBy(sAmmoRefillCounts[item - ITEM_RUPEE_GREEN + 10]); - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_BOTTLE) { temp = SLOT(item); for (i = 0; i < 4; i++) { if (gSaveContext.inventory.items[temp + i] == ITEM_NONE) { gSaveContext.inventory.items[temp + i] = item; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } } } else if (((item >= ITEM_POTION_RED) && (item <= ITEM_POE)) || (item == ITEM_MILK)) { @@ -2318,19 +2265,16 @@ u8 Item_Give(PlayState* play, u8 item) { } gSaveContext.inventory.items[temp + i] = item; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; } } } else { for (i = 0; i < 4; i++) { if (gSaveContext.inventory.items[temp + i] == ITEM_NONE) { gSaveContext.inventory.items[temp + i] = item; - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; } } } + return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item >= ITEM_WEIRD_EGG) && (item <= ITEM_CLAIM_CHECK)) { if ((item == ITEM_SAW) && CVarGetInteger("gDekuNutUpgradeFix", 0) == 0) { gSaveContext.itemGetInf[1] |= 0x8000; @@ -2354,22 +2298,17 @@ u8 Item_Give(PlayState* play, u8 item) { } else { gSaveContext.equips.buttonItems[i] = ITEM_NONE; } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } } } - GameInteractor_ExecuteOnReceiveItemHooks(item); - return ITEM_NONE; + return Return_Item(item, MOD_NONE, ITEM_NONE); } - - temp = gSaveContext.inventory.items[slot]; - osSyncPrintf("Item_Register(%d)=%d %d\n", slot, item, temp); + returnItem = gSaveContext.inventory.items[slot]; + osSyncPrintf("Item_Register(%d)=%d %d\n", slot, item, returnItem); INV_CONTENT(item) = item; - - GameInteractor_ExecuteOnReceiveItemHooks(item); - return temp; + return Return_Item(item, MOD_NONE, returnItem); } u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { @@ -2386,7 +2325,7 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { gSaveContext.isMagicAcquired = true; gSaveContext.magicFillTarget = 0x30; Magic_Fill(play); - return RG_NONE; + Return_Item_Entry(giEntry, RG_NONE); } else if (item == RG_MAGIC_DOUBLE) { if (!gSaveContext.isMagicAcquired) { gSaveContext.isMagicAcquired = true; @@ -2395,7 +2334,7 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { gSaveContext.magicFillTarget = 0x60; gSaveContext.magicLevel = 0; Magic_Fill(play); - return RG_NONE; + Return_Item_Entry(giEntry, RG_NONE); } if (item == RG_MAGIC_BEAN_PACK) { @@ -2403,14 +2342,14 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { INV_CONTENT(ITEM_BEAN) = ITEM_BEAN; AMMO(ITEM_BEAN) = 10; } - return RG_NONE; + Return_Item_Entry(giEntry, RG_NONE); } if (item == RG_DOUBLE_DEFENSE) { gSaveContext.isDoubleDefenseAcquired = true; gSaveContext.inventory.defenseHearts = 20; gSaveContext.healthAccumulator = 0x140; - return RG_NONE; + Return_Item_Entry(giEntry, RG_NONE); } if (item >= RG_BOTTLE_WITH_RED_POTION && item <= RG_BOTTLE_WITH_BIG_POE) { @@ -2448,7 +2387,7 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { } gSaveContext.inventory.items[temp + i] = item; - return ITEM_NONE; + Return_Item(item, giEntry.modIndex, RG_NONE); } } } else if ((item >= RG_FOREST_TEMPLE_SMALL_KEY && item <= RG_GANONS_CASTLE_SMALL_KEY) || @@ -2546,15 +2485,14 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { gSaveContext.sohStats.dungeonKeys[mapIndex]++; if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) { gSaveContext.inventory.dungeonKeys[mapIndex] = 1; - return RG_NONE; } else { gSaveContext.inventory.dungeonKeys[mapIndex]++; - return RG_NONE; } + Return_Item_Entry(giEntry, RG_NONE); } else if ((item >= RG_FOREST_TEMPLE_KEY_RING) && (item <= RG_GANONS_CASTLE_KEY_RING)) { gSaveContext.sohStats.dungeonKeys[mapIndex] = numOfKeysOnKeyring; gSaveContext.inventory.dungeonKeys[mapIndex] = numOfKeysOnKeyring; - return RG_NONE; + Return_Item_Entry(giEntry, RG_NONE); } else { int bitmask; if ((item >= RG_DEKU_TREE_MAP) && (item <= RG_ICE_CAVERN_MAP)) { @@ -2566,7 +2504,7 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { } gSaveContext.inventory.dungeonItems[mapIndex] |= bitmask; - return RG_NONE; + Return_Item_Entry(giEntry, RG_NONE); } } @@ -2575,14 +2513,14 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_FULL_WALLETS)) { Rupees_ChangeBy(999); } - return RG_NONE; + Return_Item_Entry(giEntry, RG_NONE); } if (item == RG_GREG_RUPEE) { Rupees_ChangeBy(1); Flags_SetRandomizerInf(RAND_INF_GREG_FOUND); gSaveContext.sohStats.timestamp[TIMESTAMP_FOUND_GREG] = GAMEPLAYSTAT_TOTAL_TIME; - return RG_NONE; + Return_Item_Entry(giEntry, RG_NONE); } temp = gSaveContext.inventory.items[slot]; @@ -6254,8 +6192,10 @@ void Interface_Update(PlayState* play) { } if (gSaveContext.rupeeAccumulator == 0) { u16 tempSaleItem = gSaveContext.pendingSale; + u16 tempSaleMod = gSaveContext.pendingSaleMod; gSaveContext.pendingSale = ITEM_NONE; - GameInteractor_ExecuteOnReceiveItemHooks(tempSaleItem); + gSaveContext.pendingSaleMod = MOD_NONE; + GameInteractor_ExecuteOnSaleEndHooks(ItemTable_RetrieveEntry(tempSaleMod,tempSaleItem)); } } else { gSaveContext.rupeeAccumulator = 0; diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 7e6486734..101cd7d03 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -108,6 +108,7 @@ void GiveLinksPocketItem() { } else if (getItemEntry.modIndex == MOD_RANDOMIZER) { if (getItemEntry.getItemId == RG_ICE_TRAP) { gSaveContext.pendingIceTrapCount++; + GameInteractor_ExecuteOnItemReceiveHooks(getItemEntry); } else { Randomizer_Item_Give(NULL, getItemEntry); } @@ -451,6 +452,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { } else if (getItem.modIndex == MOD_RANDOMIZER) { if (getItem.getItemId == RG_ICE_TRAP) { gSaveContext.pendingIceTrapCount++; + GameInteractor_ExecuteOnItemReceiveHooks(getItem); } else { Randomizer_Item_Give(NULL, getItem); } diff --git a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c index 4051ad619..6df63c4de 100644 --- a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c +++ b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c @@ -425,11 +425,14 @@ void func_809EFDD0(EnDns* this, PlayState* play) { } else { pendingGetItemId = this->dnsItemEntry->getItemId; } - gSaveContext.pendingSale = ItemTable_Retrieve(pendingGetItemId).itemId; + GetItemEntry itemEntry = ItemTable_Retrieve(pendingGetItemId); + gSaveContext.pendingSale = itemEntry.itemId; + gSaveContext.pendingSaleMod = itemEntry.modIndex; func_8002F434(&this->actor, play, pendingGetItemId, 130.0f, 100.0f); } else { GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(this->scrubIdentity.randomizerCheck, this->scrubIdentity.getItemId); gSaveContext.pendingSale = itemEntry.itemId; + gSaveContext.pendingSaleMod = itemEntry.modIndex; GiveItemEntryFromActor(&this->actor, play, itemEntry, 130.0f, 100.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c index 11a73f7e6..92605c680 100644 --- a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c +++ b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c @@ -205,7 +205,9 @@ void EnDs_OfferBluePotion(EnDs* this, PlayState* play) { case 2: // have 100 rupees and empty bottle Rupees_ChangeBy(-100); this->actor.flags &= ~ACTOR_FLAG_16; - gSaveContext.pendingSale = ItemTable_Retrieve(GI_POTION_BLUE).itemId; + GetItemEntry entry = ItemTable_Retrieve(GI_POTION_BLUE); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); this->actionFunc = EnDs_GiveBluePotion; return; diff --git a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c index d37dc3af1..011dbc1df 100644 --- a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c +++ b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c @@ -794,13 +794,17 @@ s32 EnGirlA_CanBuy_Randomizer(PlayState* play, EnGirlA* this) { } void EnGirlA_ItemGive_Arrows(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Inventory_ChangeAmmo(ITEM_BOW, this->itemCount); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_Bombs(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; switch (this->itemCount) { case 5: Item_Give(play, ITEM_BOMBS_5); @@ -819,7 +823,9 @@ void EnGirlA_ItemGive_Bombs(PlayState* play, EnGirlA* this) { } void EnGirlA_ItemGive_DekuNuts(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; switch (this->itemCount) { case 5: Item_Give(play, ITEM_NUTS_5); @@ -832,78 +838,104 @@ void EnGirlA_ItemGive_DekuNuts(PlayState* play, EnGirlA* this) { } void EnGirlA_ItemGive_DekuSticks(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Item_Give(play, ITEM_STICK); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_Longsword(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; func_800849EC(play); gSaveContext.swordHealth = 8; Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_HylianShield(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Item_Give(play, ITEM_SHIELD_HYLIAN); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_DekuShield(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Item_Give(play, ITEM_SHIELD_DEKU); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_GoronTunic(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Item_Give(play, ITEM_TUNIC_GORON); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_ZoraTunic(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Item_Give(play, ITEM_TUNIC_ZORA); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_Health(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Health_ChangeBy(play, this->itemCount); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_MilkBottle(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Item_Give(play, ITEM_MILK_BOTTLE); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_WeirdEgg(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Item_Give(play, ITEM_WEIRD_EGG); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_Unk19(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_Unk20(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_DekuSeeds(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Item_Give(play, ITEM_SEEDS_30); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_BottledItem(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; switch (this->actor.params) { case SI_FISH: Item_Give(play, ITEM_FISH); @@ -944,6 +976,7 @@ void EnGirlA_ItemGive_Randomizer(PlayState* play, EnGirlA* this) { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); gSaveContext.pendingSale = getItemEntry.itemId; + gSaveContext.pendingSaleMod = getItemEntry.modIndex; if (getItemEntry.modIndex == MOD_NONE) { // RANDOTOD: Move this into Item_Give() or some other more central location if (getItemEntry.getItemId == GI_SWORD_BGS) { @@ -954,12 +987,18 @@ void EnGirlA_ItemGive_Randomizer(PlayState* play, EnGirlA* this) { Randomizer_Item_Give(play, getItemEntry); } + if (getItemEntry.itemId == GI_ICE_TRAP || getItemEntry.itemId == RG_ICE_TRAP) { + GameInteractor_ExecuteOnItemReceiveHooks(getItemEntry); + } + Flags_SetRandomizerInf(shopItemIdentity.randomizerInf); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_BuyEvent_ShieldDiscount(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; if (this->actor.params == SI_HYLIAN_SHIELD) { if (gSaveContext.infTable[7] & 0x40) { Rupees_ChangeBy(-(this->basePrice - sShieldDiscounts[(s32)Rand_ZeroFloat(7.9f)])); @@ -970,17 +1009,23 @@ void EnGirlA_BuyEvent_ShieldDiscount(PlayState* play, EnGirlA* this) { } void EnGirlA_BuyEvent_GoronTunic(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Rupees_ChangeBy(-this->basePrice); } void EnGirlA_BuyEvent_ZoraTunic(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Rupees_ChangeBy(-this->basePrice); } void EnGirlA_BuyEvent_ObtainBombchuPack(PlayState* play, EnGirlA* this) { - gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; + GetItemEntry entry = ItemTable_Retrieve(this->getItemId); + gSaveContext.pendingSale = entry.itemId; + gSaveContext.pendingSaleMod = entry.modIndex; Rupees_ChangeBy(-this->basePrice); // Normally, buying a bombchu pack sets a flag indicating the pack is now sold out @@ -1023,6 +1068,7 @@ void EnGirlA_BuyEvent_Randomizer(PlayState* play, EnGirlA* this) { ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->randoSlotIndex); GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); gSaveContext.pendingSale = getItemEntry.itemId; + gSaveContext.pendingSaleMod = getItemEntry.modIndex; Flags_SetRandomizerInf(shopItemIdentity.randomizerInf); Rupees_ChangeBy(-this->basePrice); } diff --git a/soh/src/overlays/actors/ovl_En_Js/z_en_js.c b/soh/src/overlays/actors/ovl_En_Js/z_en_js.c index 7aa2013ea..3248ad33f 100644 --- a/soh/src/overlays/actors/ovl_En_Js/z_en_js.c +++ b/soh/src/overlays/actors/ovl_En_Js/z_en_js.c @@ -133,10 +133,13 @@ void func_80A89160(EnJs* this, PlayState* play) { !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) { GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_WASTELAND_BOMBCHU_SALESMAN, GI_BOMBCHUS_10); gSaveContext.pendingSale = itemEntry.itemId; + gSaveContext.pendingSaleMod = itemEntry.modIndex; GiveItemEntryFromActor(&this->actor, play, itemEntry, 90.0f, 10.0f); Flags_SetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN); } else { - gSaveContext.pendingSale = ItemTable_Retrieve(GI_BOMBCHUS_10).itemId; + GetItemEntry itemEntry = ItemTable_Retrieve(GI_BOMBCHUS_10); + gSaveContext.pendingSale = itemEntry.itemId; + gSaveContext.pendingSaleMod = itemEntry.modIndex; func_8002F434(&this->actor, play, GI_BOMBCHUS_10, 10000.0f, 50.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c index d2b52e0a7..3e0321b49 100644 --- a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c +++ b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c @@ -158,10 +158,13 @@ void EnMs_Sell(EnMs* this, PlayState* play) { if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) { GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN); gSaveContext.pendingSale = itemEntry.itemId; + gSaveContext.pendingSaleMod = itemEntry.modIndex; GiveItemEntryFromActor(&this->actor, play, itemEntry, 90.0f, 10.0f); BEANS_BOUGHT = 10; } else { - gSaveContext.pendingSale = ItemTable_Retrieve(GI_BEAN).itemId; + GetItemEntry entry = ItemTable_Retrieve(GI_BEAN); + gSaveContext.pendingSaleMod = entry.modIndex; + gSaveContext.pendingSale = entry.itemId; func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c index 1e55d073b..d272581ce 100644 --- a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c +++ b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c @@ -1724,6 +1724,7 @@ void EnOssan_State_ItemPurchased(EnOssan* this, PlayState* play, Player* player) } if (gSaveContext.pendingSale == ITEM_NONE) { gSaveContext.pendingSale = getItemEntry.itemId; + gSaveContext.pendingSaleMod = getItemEntry.modIndex; } if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index 344173805..c6c96969c 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -123,6 +123,7 @@ void func_80AFB768(EnSi* this, PlayState* play) { Audio_PlayFanfare_Rando(getItem); } else { gSaveContext.pendingIceTrapCount++; + GameInteractor_ExecuteOnItemReceiveHooks(getItem); Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); } } else { @@ -161,6 +162,7 @@ void func_80AFB89C(EnSi* this, PlayState* play) { Audio_PlayFanfare_Rando(getItem); } else { gSaveContext.pendingIceTrapCount++; + GameInteractor_ExecuteOnItemReceiveHooks(getItem); Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); } } else { diff --git a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c index f339e8173..d3fb9ddba 100644 --- a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c +++ b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c @@ -917,7 +917,9 @@ void func_80B15FE8(EnTa* this, PlayState* play) { this->unk_2E0 |= 2; func_80B13AA0(this, func_80B15E80, func_80B16938); Rupees_ChangeBy(-30); - gSaveContext.pendingSale = ItemTable_Retrieve(GI_MILK).itemId; + GetItemEntry itemEntry = ItemTable_Retrieve(GI_MILK); + gSaveContext.pendingSale = itemEntry.itemId; + gSaveContext.pendingSaleMod = itemEntry.modIndex; func_8002F434(&this->actor, play, GI_MILK, 10000.0f, 50.0f); break; } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 8196058f1..5a4cc4f53 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -6320,6 +6320,7 @@ s32 func_8083E5A8(Player* this, PlayState* play) { Player_SetPendingFlag(this, play); Message_StartTextbox(play, 0xF8, NULL); Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); + GameInteractor_ExecuteOnItemReceiveHooks(this->getItemEntry); gSaveContext.pendingIceTrapCount++; return 1; } @@ -12704,6 +12705,7 @@ s32 func_8084DFF4(PlayState* play, Player* this) { this->unk_862 = 0; gSaveContext.pendingIceTrapCount++; Player_SetPendingFlag(this, play); + GameInteractor_ExecuteOnItemReceiveHooks(giEntry); } this->getItemId = GI_NONE; @@ -12872,9 +12874,11 @@ void func_8084E6D4(Player* this, PlayState* play) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x, this->actor.world.pos.y + 100.0f, this->actor.world.pos.z, 0, 0, 0, 0, true); func_8083C0E8(this, play); + GameInteractor_ExecuteOnItemReceiveHooks(this->getItemEntry); } else { this->actor.colChkInfo.damage = 0; func_80837C0C(play, this, 3, 0.0f, 0.0f, 0, 20); + GameInteractor_ExecuteOnItemReceiveHooks(this->getItemEntry); this->getItemId = GI_NONE; this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; // Gameplay stats: Increment Ice Trap count