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