From 95d439bb304e93f3fb989edc4209696a95a6c9a3 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 3 Aug 2022 23:15:52 -0400 Subject: [PATCH] Adds rough ability to differentiate between rando and vanilla items.merge stashed changes from before develop-zhora merge --- soh/include/functions.h | 2 + soh/include/z64player.h | 2 +- soh/soh.vcxproj | 1 + soh/soh.vcxproj.filters | 5 +- .../item-tables/ItemTableManager.h | 20 +- .../Enhancements/item-tables/ItemTableTypes.h | 13 ++ .../Enhancements/randomizer/randomizer.cpp | 194 +++++++++++++++--- soh/soh/Enhancements/randomizer/randomizer.h | 5 +- soh/soh/OTRGlobals.cpp | 23 ++- soh/soh/OTRGlobals.h | 3 +- soh/src/code/z_parameter.c | 142 +++++++------ soh/src/code/z_sram.c | 20 +- soh/src/overlays/actors/ovl_En_Box/z_en_box.c | 19 +- .../actors/ovl_player_actor/z_player.c | 10 +- 14 files changed, 316 insertions(+), 143 deletions(-) create mode 100644 soh/soh/Enhancements/item-tables/ItemTableTypes.h diff --git a/soh/include/functions.h b/soh/include/functions.h index b185519f4..02b64ede5 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -10,6 +10,7 @@ extern "C" #endif #include "../../libultraship/libultraship/luslog.h" +#include #if defined(INCLUDE_GAME_PRINTF) && !defined(NDEBUG) #define osSyncPrintf(fmt, ...) lusprintf(__FILE__, __LINE__, 0, fmt, __VA_ARGS__) @@ -1045,6 +1046,7 @@ void Interface_LoadItemIcon1(GlobalContext* globalCtx, u16 button); void Interface_LoadItemIcon2(GlobalContext* globalCtx, u16 button); void func_80084BF4(GlobalContext* globalCtx, u16 flag); u8 Item_Give(GlobalContext* globalCtx, u8 item); +u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry); u8 Item_CheckObtainability(u8 item); void Inventory_DeleteItem(u16 item, u16 invSlot); s32 Inventory_ReplaceItem(GlobalContext* globalCtx, u16 oldItem, u16 newItem); diff --git a/soh/include/z64player.h b/soh/include/z64player.h index 3c2c7c3cd..ff6291fd8 100644 --- a/soh/include/z64player.h +++ b/soh/include/z64player.h @@ -626,6 +626,6 @@ typedef struct Player { /* 0x0A87 */ u8 unk_A87; /* 0x0A88 */ Vec3f unk_A88; // previous body part 0 position /* 0x0A94 */ PendingFlag pendingFlag; -} Player; // size = 0xAA0 +} Player; // size = 0xA94 #endif diff --git a/soh/soh.vcxproj b/soh/soh.vcxproj index 6c80d3cee..00c70dfa4 100644 --- a/soh/soh.vcxproj +++ b/soh/soh.vcxproj @@ -949,6 +949,7 @@ + diff --git a/soh/soh.vcxproj.filters b/soh/soh.vcxproj.filters index 210cb1022..b175f5ca7 100644 --- a/soh/soh.vcxproj.filters +++ b/soh/soh.vcxproj.filters @@ -4086,7 +4086,10 @@ Header Files\soh\Enhancements\randomizer - Header Files + Header Files\soh\Enhancements\item-tables + + + Header Files\soh\Enhancements\item-tables diff --git a/soh/soh/Enhancements/item-tables/ItemTableManager.h b/soh/soh/Enhancements/item-tables/ItemTableManager.h index 347c0c4a2..fd827c3fa 100644 --- a/soh/soh/Enhancements/item-tables/ItemTableManager.h +++ b/soh/soh/Enhancements/item-tables/ItemTableManager.h @@ -1,30 +1,16 @@ #pragma once - -#include +#include "ItemTableTypes.h" #define CHEST_ANIM_SHORT 0 #define CHEST_ANIM_LONG 1 -typedef struct { - /* 0x00 */ uint8_t itemId; - /* 0x01 */ uint8_t field; // various bit-packed data - /* 0x02 */ int8_t gi; // defines the draw id and chest opening animation - /* 0x03 */ uint8_t textId; - /* 0x04 */ uint16_t objectId; - /* 0x06 */ uint16_t modIndex; // 0 = Vanilla, 1 = Randomizer, future mods will increment up? -} GetItemEntry; // size = 0x06 - #define GET_ITEM(itemId, objectId, drawId, textId, field, chestAnim) \ { itemId, field, (chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1), textId, objectId } #define GET_ITEM_NONE \ - { ITEM_NONE, 0, 0, 0, OBJECT_INVALID } - -#ifdef __cplusplus + { 0, 0, 0, 0, 0 } #include -#include "z64item.h" -#include "z64object.h" typedef std::unordered_map ItemTable; @@ -44,5 +30,3 @@ class ItemTableManager { ItemTable* RetrieveItemTable(std::string tableID); }; - -#endif \ No newline at end of file diff --git a/soh/soh/Enhancements/item-tables/ItemTableTypes.h b/soh/soh/Enhancements/item-tables/ItemTableTypes.h new file mode 100644 index 000000000..ed71bfabe --- /dev/null +++ b/soh/soh/Enhancements/item-tables/ItemTableTypes.h @@ -0,0 +1,13 @@ +#pragma once +#ifdef __cplusplus +#include +#endif + +typedef struct { + /* 0x00 */ uint8_t itemId; + /* 0x01 */ uint8_t field; // various bit-packed data + /* 0x02 */ int8_t gi; // defines the draw id and chest opening animation + /* 0x03 */ uint8_t textId; + /* 0x04 */ uint16_t objectId; + /* 0x06 */ uint16_t modIndex; // 0 = Vanilla, 1 = Randomizer, future mods will increment up? +} GetItemEntry; // size = 0x06 diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 18e79badb..46023f507 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2030,8 +2030,8 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) case RG_MAGIC_BEAN_PACK: return GI_BEAN; //todo make it 10 of them - case RG_DOUBLE_DEFENSE: - return GI_DOUBLE_DEFENSE; + /*case RG_DOUBLE_DEFENSE: + return GI_DOUBLE_DEFENSE;*/ case RG_WEIRD_EGG: return GI_WEIRD_EGG; @@ -2160,9 +2160,9 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) case RG_PROGRESSIVE_MAGIC_METER: switch (gSaveContext.magicLevel) { case 0: - return GI_SINGLE_MAGIC; + return (GetItemID)RG_MAGIC_SINGLE; case 1: - return GI_DOUBLE_MAGIC; + return (GetItemID)RG_MAGIC_DOUBLE; } return GI_RUPEE_BLUE; @@ -2182,7 +2182,7 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) return GI_BOTTLE; case RG_BOTTLE_WITH_MILK: return GI_MILK_BOTTLE; - case RG_BOTTLE_WITH_RED_POTION: + /*case RG_BOTTLE_WITH_RED_POTION: return GI_BOTTLE_WITH_RED_POTION; case RG_BOTTLE_WITH_GREEN_POTION: return GI_BOTTLE_WITH_GREEN_POTION; @@ -2227,7 +2227,7 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) case RG_NOCTURNE_OF_SHADOW: return GI_NOCTURNE_OF_SHADOW; case RG_PRELUDE_OF_LIGHT: - return GI_PRELUDE_OF_LIGHT; + return GI_PRELUDE_OF_LIGHT;*/ // todo implement dungeon-specific maps/compasses case RG_DEKU_TREE_MAP: @@ -2290,7 +2290,7 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) case RG_GANONS_CASTLE_KEY_RING: return GI_RUPEE_BLUE; - case RG_KOKIRI_EMERALD: + /*case RG_KOKIRI_EMERALD: return GI_STONE_KOKIRI; case RG_GORON_RUBY: return GI_STONE_GORON; @@ -2308,7 +2308,7 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) case RG_SHADOW_MEDALLION: return GI_MEDALLION_SHADOW; case RG_LIGHT_MEDALLION: - return GI_MEDALLION_LIGHT; + return GI_MEDALLION_LIGHT;*/ case RG_RECOVERY_HEART: return GI_HEART; @@ -2387,11 +2387,60 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) case RG_HINT: return GI_RUPEE_BLUE; //todo - default: + default: { + if (IsGetItemRandoExclusive(randoGet)) { + return (GetItemID)randoGet; + } return ogItemId; + } } } +bool Randomizer::IsGetItemRandoExclusive(RandomizerGet randoGet) { + switch (randoGet) { + case RG_LIGHT_MEDALLION: + case RG_FOREST_MEDALLION: + case RG_FIRE_MEDALLION: + case RG_WATER_MEDALLION: + case RG_SHADOW_MEDALLION: + case RG_SPIRIT_MEDALLION: + case RG_KOKIRI_EMERALD: + case RG_GORON_RUBY: + case RG_ZORA_SAPPHIRE: + case RG_ZELDAS_LULLABY: + case RG_SUNS_SONG: + case RG_EPONAS_SONG: + case RG_SONG_OF_STORMS: + case RG_SONG_OF_TIME: + case RG_SARIAS_SONG: + case RG_MINUET_OF_FOREST: + case RG_BOLERO_OF_FIRE: + case RG_SERENADE_OF_WATER: + case RG_NOCTURNE_OF_SHADOW: + case RG_REQUIEM_OF_SPIRIT: + case RG_PRELUDE_OF_LIGHT: + case RG_PROGRESSIVE_MAGIC_METER: + case RG_DOUBLE_DEFENSE: + case RG_BOTTLE_WITH_RED_POTION: + case RG_BOTTLE_WITH_GREEN_POTION: + case RG_BOTTLE_WITH_BLUE_POTION: + case RG_BOTTLE_WITH_FAIRY: + case RG_BOTTLE_WITH_FISH: + case RG_BOTTLE_WITH_BLUE_FIRE: + case RG_BOTTLE_WITH_BUGS: + case RG_BOTTLE_WITH_POE: + case RG_BOTTLE_WITH_BIG_POE: + return true; + default: + return false; + } +} + +bool Randomizer::CheckContainsRandoItem(RandomizerCheck randoCheck) { + RandomizerGet randoGet = this->itemLocations[randoCheck]; + return IsGetItemRandoExclusive(randoGet); +} + std::string Randomizer::GetAdultAltarText() const { return this->adultAltarText; } @@ -4732,31 +4781,34 @@ void DrawRandoEditor(bool& open) { void InitRandoItemTable() { GetItemEntry getItemTable[] = { - GET_ITEM(RG_LIGHT_MEDALLION, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_FOREST_MEDALLION, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_FIRE_MEDALLION, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_WATER_MEDALLION, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_SHADOW_MEDALLION, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_SPIRIT_MEDALLION, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG), + // The first several entries have ItemIDs from vanilla, but not GetItemIDs or entries in sGetItemTable + GET_ITEM(ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_ZELDAS_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_SUNS_SONG, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_EPONAS_SONG, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_SONG_OF_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_SONG_OF_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_SARIAS_SONG, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_SUN, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_EPONA, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_SARIA, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_MINUET_OF_FOREST, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_BOLERO_OF_FIRE, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_SERENADE_OF_WATER, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_NOCTURNE_OF_SHADOW, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_REQUIEM_OF_SPIRIT, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG), - GET_ITEM(RG_PRELUDE_OF_LIGHT, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG), + // Starting here, these do not have ItemIDs or GetItemIDs from vanilla, so I'm using their + // RandomizerGet enum values for both. GET_ITEM(RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG), GET_ITEM(RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG), GET_ITEM(RG_DOUBLE_DEFENSE, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xE9, 0x80, CHEST_ANIM_LONG), @@ -4773,14 +4825,92 @@ void InitRandoItemTable() { }; ItemTableManager::Instance->AddItemTable("Randomizer"); for (int i = 0; i < ARRAY_SIZE(getItemTable); i++) { - getItemTable[i].modIndex = MOD_RANDOMIZER; - ItemTableManager::Instance->AddItemEntry("Randomizer", getItemTable[i].itemId, getItemTable[i]); + if (i < 21) { + // We want to use vanilla Give_Item code for indices 0-20 since + // vanilla already handles that. + getItemTable[i].modIndex = MOD_VANILLA; + } else { + // Mark these as randomizer items so we use the rando exclusive + // Give_Item_Randomizer for these. + getItemTable[i].modIndex = MOD_RANDOMIZER; + } + uint8_t getItemID; + switch (getItemTable[i].itemId) { + case ITEM_MEDALLION_LIGHT: + getItemID = RG_LIGHT_MEDALLION; + break; + case ITEM_MEDALLION_FOREST: + getItemID = RG_FOREST_MEDALLION; + break; + case ITEM_MEDALLION_FIRE: + getItemID = RG_FIRE_MEDALLION; + break; + case ITEM_MEDALLION_WATER: + getItemID = RG_WATER_MEDALLION; + break; + case ITEM_MEDALLION_SHADOW: + getItemID = RG_SHADOW_MEDALLION; + break; + case ITEM_MEDALLION_SPIRIT: + getItemID = RG_SPIRIT_MEDALLION; + break; + case ITEM_KOKIRI_EMERALD: + getItemID = RG_KOKIRI_EMERALD; + break; + case ITEM_GORON_RUBY: + getItemID = RG_GORON_RUBY; + break; + case ITEM_ZORA_SAPPHIRE: + getItemID = RG_ZORA_SAPPHIRE; + break; + case ITEM_SONG_LULLABY: + getItemID = RG_ZELDAS_LULLABY; + break; + case ITEM_SONG_SUN: + getItemID = RG_SUNS_SONG; + break; + case ITEM_SONG_EPONA: + getItemID = RG_EPONAS_SONG; + break; + case ITEM_SONG_STORMS: + getItemID = RG_SONG_OF_STORMS; + break; + case ITEM_SONG_TIME: + getItemID = RG_SONG_OF_TIME; + break; + case ITEM_SONG_SARIA: + getItemID = RG_SARIAS_SONG; + break; + case ITEM_SONG_MINUET: + getItemID = RG_MINUET_OF_FOREST; + break; + case ITEM_SONG_BOLERO: + getItemID = RG_BOLERO_OF_FIRE; + break; + case ITEM_SONG_SERENADE: + getItemID = RG_SERENADE_OF_WATER; + break; + case ITEM_SONG_NOCTURNE: + getItemID = RG_NOCTURNE_OF_SHADOW; + break; + case ITEM_SONG_REQUIEM: + getItemID = RG_REQUIEM_OF_SPIRIT; + break; + case ITEM_SONG_PRELUDE: + getItemID = RG_PRELUDE_OF_LIGHT; + break; + default: + getItemID = getItemTable[i].itemId; + break; + } + ItemTableManager::Instance->AddItemEntry("Randomizer", getItemID, getItemTable[i]); } } void InitRando() { SohImGui::AddWindow("Randomizer", "Randomizer Settings", DrawRandoEditor); + InitRandoItemTable(); } extern "C" { diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index e13303b19..5c0686a51 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -24,6 +24,8 @@ class Randomizer { void ParseRandomizerSettingsFile(const char* spoilerFileName); void ParseHintLocationsFile(const char* spoilerFileName); void ParseItemLocationsFile(const char* spoilerFileName, bool silent); + bool IsGetItemRandoExclusive(RandomizerGet randoGet); + public: Randomizer(); @@ -37,7 +39,7 @@ class Randomizer { void LoadHintLocations(const char* spoilerFileName); void LoadItemLocations(const char* spoilerFileName, bool silent); u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey); - RandomizerCheck GetCheckFromActor(s16 actorId, s16 actorParams, s16 sceneNum); + RandomizerCheck GetCheckFromActor(s16 sceneNum, s16 actorId, s16 actorParams); std::string GetChildAltarText() const; std::string GetAdultAltarText() const; std::string GetGanonText() const; @@ -45,6 +47,7 @@ class Randomizer { std::string GetHintFromCheck(RandomizerCheck check); GetItemID GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); GetItemID GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum); + bool CheckContainsRandoItem(RandomizerCheck randoCheck); }; #ifdef __cplusplus diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index caebb1a02..c12febe55 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1648,10 +1648,20 @@ extern "C" int Randomizer_CopyHintFromCheck(RandomizerCheck check, char* buffer, } extern "C" s32 Randomizer_GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum) { + if (OTRGlobals::Instance->gRandomizer->CheckContainsRandoItem(OTRGlobals::Instance->gRandomizer->GetCheckFromActor(sceneNum, actorId, actorParams))) { + OTRGlobals::Instance->getItemModIndex = MOD_RANDOMIZER; + } else { + OTRGlobals::Instance->getItemModIndex = MOD_VANILLA; + } return OTRGlobals::Instance->gRandomizer->GetRandomizedItemId(ogId, actorId, actorParams, sceneNum); } extern "C" s32 Randomizer_GetItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId) { + if (OTRGlobals::Instance->gRandomizer->CheckContainsRandoItem(randomizerCheck)) { + OTRGlobals::Instance->getItemModIndex = MOD_RANDOMIZER; + } else { + OTRGlobals::Instance->getItemModIndex = MOD_VANILLA; + } return OTRGlobals::Instance->gRandomizer->GetRandomizedItemIdFromKnownCheck(randomizerCheck, ogId); } @@ -1660,5 +1670,14 @@ extern "C" bool Randomizer_ItemIsIceTrap(RandomizerCheck randomizerCheck, GetIte } extern "C" GetItemEntry ItemTable_Retrieve(int16_t getItemID) { - return ItemTableManager::Instance->RetrieveItemEntry("Vanilla", getItemID); -} + std::string itemTableID; + + if (OTRGlobals::Instance->getItemModIndex == MOD_VANILLA) { + itemTableID = "Vanilla"; + } else { + itemTableID = "Randomizer"; + getItemID++; // counteracts the - 1 offset used for vanilla table + } + + return ItemTableManager::Instance->RetrieveItemEntry(itemTableID, getItemID); +} \ No newline at end of file diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index ae05c5fe4..76c504877 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -5,7 +5,7 @@ #include "GlobalCtx2.h" #include "SaveManager.h" -#include +#include #ifdef __cplusplus #include "Enhancements/savestates.h" @@ -19,6 +19,7 @@ public: std::shared_ptr context; std::shared_ptr gSaveStateMgr; std::shared_ptr gRandomizer; + uint16_t getItemModIndex; OTRGlobals(); ~OTRGlobals(); diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 44d529587..0936f10fd 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1578,70 +1578,6 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { osSyncPrintf("item_get_setting=%d pt=%d z=%x\n", item, slot, gSaveContext.inventory.items[slot]); osSyncPrintf(VT_RST); - if (item == ITEM_SINGLE_MAGIC) { - gSaveContext.magicAcquired = true; - gSaveContext.unk_13F6 = 0x30; - Magic_Fill(globalCtx); - return ITEM_NONE; - } else if (item == ITEM_DOUBLE_MAGIC) { - if (!gSaveContext.magicAcquired) { - gSaveContext.magicAcquired = true; - } - gSaveContext.doubleMagic = true; - gSaveContext.unk_13F6 = 0x60; - gSaveContext.magicLevel = 0; - Magic_Fill(globalCtx); - return ITEM_NONE; - } - - if (item == ITEM_DOUBLE_DEFENSE) { - gSaveContext.doubleDefense = true; - gSaveContext.inventory.defenseHearts = 20; - gSaveContext.healthAccumulator = 0x140; - return ITEM_NONE; - } - - if (item >= ITEM_BOTTLE_WITH_RED_POTION && - item <= ITEM_BOTTLE_WITH_BIG_POE) { - temp = SLOT(ITEM_BOTTLE); - for (i = 0; i < 4; i++) { - if (gSaveContext.inventory.items[temp + i] == ITEM_NONE) { - switch (item) { - case ITEM_BOTTLE_WITH_RED_POTION: - item = ITEM_POTION_RED; - break; - case ITEM_BOTTLE_WITH_GREEN_POTION: - item = ITEM_POTION_GREEN; - break; - case ITEM_BOTTLE_WITH_BLUE_POTION: - item = ITEM_POTION_BLUE; - break; - case ITEM_BOTTLE_WITH_FAIRY: - item = ITEM_FAIRY; - break; - case ITEM_BOTTLE_WITH_FISH: - item = ITEM_FISH; - break; - case ITEM_BOTTLE_WITH_BLUE_FIRE: - item = ITEM_BLUE_FIRE; - break; - case ITEM_BOTTLE_WITH_BUGS: - item = ITEM_BUG; - break; - case ITEM_BOTTLE_WITH_POE: - item = ITEM_POE; - break; - case ITEM_BOTTLE_WITH_BIG_POE: - item = ITEM_BIG_POE; - break; - } - - gSaveContext.inventory.items[temp + i] = item; - return ITEM_NONE; - } - } - } - if ((item >= ITEM_MEDALLION_FOREST) && (item <= ITEM_MEDALLION_LIGHT)) { gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_MEDALLION_FOREST + QUEST_MEDALLION_FOREST]; @@ -2179,6 +2115,84 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { return temp; } +u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry) { + uint16_t item = giEntry.itemId; + uint16_t temp; + uint16_t i; + uint16_t slot; + + slot = SLOT(item); + if (item == RG_MAGIC_SINGLE) { + gSaveContext.magicAcquired = true; + gSaveContext.unk_13F6 = 0x30; + Magic_Fill(globalCtx); + return RG_NONE; + } else if (item == RG_MAGIC_DOUBLE) { + if (!gSaveContext.magicAcquired) { + gSaveContext.magicAcquired = true; + } + gSaveContext.doubleMagic = true; + gSaveContext.unk_13F6 = 0x60; + gSaveContext.magicLevel = 0; + Magic_Fill(globalCtx); + return RG_NONE; + } + + if (item == RG_DOUBLE_DEFENSE) { + gSaveContext.doubleDefense = true; + gSaveContext.inventory.defenseHearts = 20; + gSaveContext.healthAccumulator = 0x140; + return RG_NONE; + } + + if (item >= RG_BOTTLE_WITH_RED_POTION && item <= RG_BOTTLE_WITH_BIG_POE) { + temp = SLOT(ITEM_BOTTLE); + for (i = 0; i < 4; i++) { + if (gSaveContext.inventory.items[temp + i] == RG_NONE) { + switch (item) { + case RG_BOTTLE_WITH_RED_POTION: + item = ITEM_POTION_RED; + break; + case RG_BOTTLE_WITH_GREEN_POTION: + item = ITEM_POTION_GREEN; + break; + case RG_BOTTLE_WITH_BLUE_POTION: + item = ITEM_POTION_BLUE; + break; + case RG_BOTTLE_WITH_FAIRY: + item = ITEM_FAIRY; + break; + case RG_BOTTLE_WITH_FISH: + item = ITEM_FISH; + break; + case RG_BOTTLE_WITH_BLUE_FIRE: + item = ITEM_BLUE_FIRE; + break; + case RG_BOTTLE_WITH_BUGS: + item = ITEM_BUG; + break; + case RG_BOTTLE_WITH_POE: + item = ITEM_POE; + break; + case RG_BOTTLE_WITH_BIG_POE: + item = ITEM_BIG_POE; + break; + } + + gSaveContext.inventory.items[temp + i] = item; + return RG_NONE; + } + } + } + + temp = gSaveContext.inventory.items[slot]; + osSyncPrintf("Item_Register(%d)=%d %d\n", slot, item, temp); + INV_CONTENT(item) = item; + + return temp; +} + + u8 Item_CheckObtainability(u8 item) { s16 i; s16 slot = SLOT(item); diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 080c5ea9d..8eb681cb9 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -367,43 +367,43 @@ void GiveLinkSong(GetItemID getItemId) { gSaveContext.inventory.questItems |= bitMask; } -void GiveLinkDungeonReward(GetItemID getItemId) { +void GiveLinkDungeonReward(uint16_t getItemId) { s16 item; u8 medallion = 0; switch (getItemId) { - case GI_MEDALLION_FOREST: + case RG_FOREST_MEDALLION: item = ITEM_MEDALLION_FOREST; medallion = 1; break; - case GI_MEDALLION_FIRE: + case RG_FIRE_MEDALLION: item = ITEM_MEDALLION_FIRE; medallion = 1; break; - case GI_MEDALLION_WATER: + case RG_WATER_MEDALLION: item = ITEM_MEDALLION_WATER; medallion = 1; break; - case GI_MEDALLION_SHADOW: + case RG_SHADOW_MEDALLION: item = ITEM_MEDALLION_SHADOW; medallion = 1; break; - case GI_MEDALLION_SPIRIT: + case RG_SPIRIT_MEDALLION: item = ITEM_MEDALLION_SPIRIT; medallion = 1; break; - case GI_MEDALLION_LIGHT: + case RG_LIGHT_MEDALLION: item = ITEM_MEDALLION_LIGHT; medallion = 1; break; - case GI_STONE_KOKIRI: + case RG_KOKIRI_EMERALD: item = ITEM_KOKIRI_EMERALD; break; - case GI_STONE_GORON: + case RG_GORON_RUBY: item = ITEM_GORON_RUBY; break; - case GI_STONE_ZORA: + case RG_ZORA_SAPPHIRE: item = ITEM_ZORA_SAPPHIRE; break; } diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index 533ba593a..b6c110581 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -70,6 +70,7 @@ static InitChainEntry sInitChain[] = { }; static UNK_TYPE sUnused; +int32_t sItem; void EnBox_SetupAction(EnBox* this, EnBoxActionFunc actionFunc) { this->actionFunc = actionFunc; @@ -445,40 +446,40 @@ void EnBox_WaitOpen(EnBox* this, GlobalContext* globalCtx) { func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos); if (sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f && Player_IsFacingActor(&this->dyna.actor, 0x3000, globalCtx)) { - int32_t item = Randomizer_GetRandomizedItemId(this->dyna.actor.params >> 5 & 0x7F, this->dyna.actor.id, this->dyna.actor.params, globalCtx->sceneNum); + sItem = Randomizer_GetRandomizedItemId(this->dyna.actor.params >> 5 & 0x7F, this->dyna.actor.id, this->dyna.actor.params, globalCtx->sceneNum); // RANDOTODO treasure chest game rando if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { if (gSaveContext.n64ddFlag && globalCtx->sceneNum == 16 && (this->dyna.actor.params & 0x60) != 0x20) { if((this->dyna.actor.params & 0xF) < 2) { if(Flags_GetCollectible(globalCtx, 0x1B)) { - item = GI_RUPEE_BLUE; + sItem = GI_RUPEE_BLUE; } } if((this->dyna.actor.params & 0xF) >= 2 && (this->dyna.actor.params & 0xF) < 4) { if(Flags_GetCollectible(globalCtx, 0x1C)) { - item = GI_RUPEE_BLUE; + sItem = GI_RUPEE_BLUE; } } if((this->dyna.actor.params & 0xF) >= 4 && (this->dyna.actor.params & 0xF) < 6) { if(Flags_GetCollectible(globalCtx, 0x1D)) { - item = GI_RUPEE_BLUE; + sItem = GI_RUPEE_BLUE; } } if((this->dyna.actor.params & 0xF) >= 6 && (this->dyna.actor.params & 0xF) < 8) { if(Flags_GetCollectible(globalCtx, 0x1E)) { - item = GI_RUPEE_BLUE; + sItem = GI_RUPEE_BLUE; } } if((this->dyna.actor.params & 0xF) >= 8 && (this->dyna.actor.params & 0xF) < 10) { if(Flags_GetCollectible(globalCtx, 0x1F)) { - item = GI_RUPEE_BLUE; + sItem = GI_RUPEE_BLUE; } } } } - func_8002F554(&this->dyna.actor, globalCtx, 0 - item); + func_8002F554(&this->dyna.actor, globalCtx, 0 - sItem); } if (Flags_GetTreasure(globalCtx, this->dyna.actor.params & 0x1F)) { EnBox_SetupAction(this, EnBox_Open); @@ -590,9 +591,7 @@ void EnBox_Update(Actor* thisx, GlobalContext* globalCtx) { } if (((!gSaveContext.n64ddFlag && ((this->dyna.actor.params >> 5 & 0x7F) == 0x7C)) || - (gSaveContext.n64ddFlag && Randomizer_GetRandomizedItemId(this->dyna.actor.params >> 5 & 0x7F, - this->dyna.actor.id, this->dyna.actor.params, - globalCtx->sceneNum) == GI_ICE_TRAP)) && + (gSaveContext.n64ddFlag && sItem == GI_ICE_TRAP)) && this->actionFunc == EnBox_Open && this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100) EnBox_SpawnIceSmoke(this, globalCtx); } 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 58bc611c2..9aeaab84a 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -12715,9 +12715,13 @@ s32 func_8084DFF4(GlobalContext* globalCtx, Player* this) { gSaveContext.swordHealth = 8; } - Message_StartTextbox(globalCtx, giEntry->textId, &this->actor); - Item_Give(globalCtx, giEntry->itemId); - + Message_StartTextbox(globalCtx, giEntry.textId, &this->actor); + if (giEntry.modIndex == 0) { + Item_Give(globalCtx, giEntry.itemId); + } + else { + Randomizer_Item_Give(globalCtx, giEntry); + } Player_SetPendingFlag(this, globalCtx); if (((this->getItemId >= GI_RUPEE_GREEN) && (this->getItemId <= GI_RUPEE_RED)) ||