diff --git a/.gitmodules b/.gitmodules index 7098d9d08..f5b67b3ab 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,4 +6,4 @@ url = https://github.com/harbourmasters/ZAPDTR [submodule "OTRExporter"] path = OTRExporter - url = https://github.com/harbourmasters/OTRExporter + url = https://github.com/harbourmasters/OTRExporter/ diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL new file mode 100644 index 000000000..6e3cbc204 --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_0 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_0 new file mode 100644 index 000000000..34ff33a71 --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_0 @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_1 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_1 new file mode 100644 index 000000000..e406505e8 --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_1 @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_2 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_2 new file mode 100644 index 000000000..d93755356 --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_2 @@ -0,0 +1,7 @@ + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_3 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_3 new file mode 100644 index 000000000..87fb8da01 --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_3 @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_4 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_4 new file mode 100644 index 000000000..6e436b142 --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_4 @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_0 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_0 new file mode 100644 index 000000000..ed4b6e1c0 --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_0 @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_1 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_1 new file mode 100644 index 000000000..d2728aae4 --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_1 @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_2 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_2 new file mode 100644 index 000000000..eb0050c03 --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_2 @@ -0,0 +1,6 @@ + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_3 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_3 new file mode 100644 index 000000000..f124650c8 --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_3 @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_4 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_4 new file mode 100644 index 000000000..2bbe7895e --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_4 @@ -0,0 +1,267 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Gem_eyes b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Gem_eyes new file mode 100644 index 000000000..07364ba3a --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Gem_eyes @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_black b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_black new file mode 100644 index 000000000..6aee093d9 --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_black @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_eyes b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_eyes new file mode 100644 index 000000000..c08beb94a --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_eyes @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_horns b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_horns new file mode 100644 index 000000000..78d2a531c --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_horns @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_surface b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_surface new file mode 100644 index 000000000..e15a4dce4 --- /dev/null +++ b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_surface @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_boss_soul/noise_tex b/soh/assets/custom/objects/object_boss_soul/noise_tex new file mode 100644 index 000000000..aaf4e331f Binary files /dev/null and b/soh/assets/custom/objects/object_boss_soul/noise_tex differ diff --git a/soh/assets/custom/objects/object_boss_soul/noise_tex_copy b/soh/assets/custom/objects/object_boss_soul/noise_tex_copy new file mode 100644 index 000000000..a6d6cf945 Binary files /dev/null and b/soh/assets/custom/objects/object_boss_soul/noise_tex_copy differ diff --git a/soh/assets/soh_assets.h b/soh/assets/soh_assets.h index 2b193053c..16a2f5cd0 100644 --- a/soh/assets/soh_assets.h +++ b/soh/assets/soh_assets.h @@ -56,6 +56,9 @@ static const ALIGN_ASSET(2) char gTriforcePiece2DL[] = dgTriforcePiece2DL; #define dgTriforcePieceCompletedDL "__OTR__objects/object_triforce_completed/gTriforcePieceCompletedDL" static const ALIGN_ASSET(2) char gTriforcePieceCompletedDL[] = dgTriforcePieceCompletedDL; +#define dgBossSoulSkullDL "__OTR__objects/object_boss_soul/gGIBossSoulSkullDL" +static const ALIGN_ASSET(2) char gBossSoulSkullDL[] = dgBossSoulSkullDL; + // overlays #define dgOptionsDividerChangeLangVtx "__OTR__overlays/ovl_file_choose/gOptionsDividerChangeLangVtx" static const ALIGN_ASSET(2) char gOptionsDividerChangeLangVtx[] = dgOptionsDividerChangeLangVtx; diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h index 42c9c91c0..1daddbf17 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.h +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h @@ -505,6 +505,16 @@ const std::vector flagTables = { { RAND_INF_CHILD_FISHING, "RAND_INF_CHILD_FISHING" }, { RAND_INF_ADULT_FISHING, "RAND_INF_ADULT_FISHING" }, { RAND_INF_10_BIG_POES, "RAND_INF_10_BIG_POES" }, + + { RAND_INF_GOHMA_SOUL, "RAND_INF_GOHMA_SOUL" }, + { RAND_INF_KING_DODONGO_SOUL, "RAND_INF_KING_DODONGO_SOUL" }, + { RAND_INF_BARINADE_SOUL, "RAND_INF_BARINADE_SOUL" }, + { RAND_INF_PHANTOM_GANON_SOUL, "RAND_INF_PHANTOM_GANON_SOUL" }, + { RAND_INF_VOLVAGIA_SOUL, "RAND_INF_VOLVAGIA_SOUL" }, + { RAND_INF_MORPHA_SOUL, "RAND_INF_MORPHA_SOUL" }, + { RAND_INF_BONGO_BONGO_SOUL, "RAND_INF_BONGO_BONGO_SOUL" }, + { RAND_INF_TWINROVA_SOUL, "RAND_INF_TWINROVA_SOUL" }, + { RAND_INF_GANON_SOUL, "RAND_INF_GANON_SOUL" }, } }, }; diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 73110a7d6..34aa8af15 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -1039,6 +1039,64 @@ void RegisterRandomizerSheikSpawn() { }); } +//Boss souls require an additional item (represented by a RAND_INF) to spawn a boss in a particular lair +void RegisterBossSouls() { + GameInteractor::Instance->RegisterGameHook([](void* actor) { + if (!gPlayState) return; + if (!IS_RANDO || !(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_BOSS_SOULS))) return; + RandomizerInf rand_inf = RAND_INF_MAX; + Actor* actual = (Actor*)actor; + switch (gPlayState->sceneNum){ + case SCENE_DEKU_TREE_BOSS: + rand_inf = RAND_INF_GOHMA_SOUL; + break; + case SCENE_DODONGOS_CAVERN_BOSS: + rand_inf = RAND_INF_KING_DODONGO_SOUL; + break; + case SCENE_JABU_JABU_BOSS: + rand_inf = RAND_INF_BARINADE_SOUL; + break; + case SCENE_FOREST_TEMPLE_BOSS: + rand_inf = RAND_INF_PHANTOM_GANON_SOUL; + break; + case SCENE_FIRE_TEMPLE_BOSS: + rand_inf = RAND_INF_VOLVAGIA_SOUL; + break; + case SCENE_WATER_TEMPLE_BOSS: + rand_inf = RAND_INF_MORPHA_SOUL; + break; + case SCENE_SHADOW_TEMPLE_BOSS: + rand_inf = RAND_INF_BONGO_BONGO_SOUL; + break; + case SCENE_SPIRIT_TEMPLE_BOSS: + rand_inf = RAND_INF_TWINROVA_SOUL; + break; + case SCENE_GANONDORF_BOSS: + case SCENE_GANON_BOSS: + if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_BOSS_SOULS) == RO_BOSS_SOULS_ON_PLUS_GANON) { + rand_inf = RAND_INF_GANON_SOUL; + } + break; + default: break; + } + + //Deletes all actors in the boss category if the soul isn't found. + //Some actors, like Dark Link, Arwings, and Zora's Sapphire...?, are in this category despite not being actual bosses, + //so ignore any "boss" if `rand_inf` doesn't change from RAND_INF_MAX. + if (rand_inf != RAND_INF_MAX) { + if (!Flags_GetRandomizerInf(rand_inf) && actual->category == ACTORCAT_BOSS) { + Actor_Delete(&gPlayState->actorCtx, actual, gPlayState); + } + //Special case for Phantom Ganon's horse (and fake), as they're considered "background actors", + //but still control the boss fight flow. + if (!Flags_GetRandomizerInf(RAND_INF_PHANTOM_GANON_SOUL) && actual->id == ACTOR_EN_FHG) { + Actor_Delete(&gPlayState->actorCtx, actual, gPlayState); + } + } + }); + +} + void InitMods() { RegisterTTS(); RegisterInfiniteMoney(); @@ -1066,5 +1124,6 @@ void InitMods() { RegisterEnemyDefeatCounts(); RegisterAltTrapTypes(); RegisterRandomizerSheikSpawn(); + RegisterBossSouls(); NameTag_RegisterHooks(); } diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp index efe4a9424..0e460a024 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp @@ -1939,6 +1939,114 @@ void HintTable_Init_Item() { Text{"a Piece of the Triforce", /*french*/"un fragment de la Triforce", /*spanish*/"un fragmento de la Trifuerza"} ); + hintTable[RHT_GOHMA_SOUL] = HintText::Item({ + //obscure text + Text{"an invasive soul", "", ""}, + Text{"some spider essence", "", ""}, + }, { + //ambiguous text + Text{"something webbed", "", ""} + }, { + //clear text + Text{"the soul of Gohma", "", ""}} + ); + + hintTable[RHT_KING_DODONGO_SOUL] = HintText::Item({ + //obscure text + Text{"a royal soul", "", ""}, + Text{"some reptile essence", "", ""}, + }, { + //ambiguous text + Text{"something explosive", "", ""} + }, { + //clear text + Text{"the soul of King Dodongo", "", ""}} + ); + + hintTable[RHT_BARINADE_SOUL] = HintText::Item({ + //obscure text + Text{"an infectuous soul", "", ""}, + Text{"some parasitic essence", "", ""}, + }, { + //ambiguous text + Text{"something fishy", "", ""} + }, { + //clear text + Text("the soul of Barinade", "", "")} + ); + + hintTable[RHT_PHANTOM_GANON_SOUL] = HintText::Item({ + //obscure text + Text{"a duplicate soul", "", ""}, + Text{"some illusionary essence", "", ""}, + }, { + //ambiguous text + Text{"something spectral", "", ""} + }, { + //clear text + Text{"the soul of Phantom Ganon", "", ""}} + ); + + hintTable[RHT_VOLVAGIA_SOUL] = HintText::Item({ + //obscure text + Text{"a draconic soul", "", ""}, + Text{"some magmatic essence", "", ""}, + }, { + //ambiguous text + Text{"something hot", "", ""} + }, { + //clear text + Text{"the soul of Volvagia", "", ""}} + ); + + hintTable[RHT_MORPHA_SOUL] = HintText::Item({ + //obscure text + Text{"an aquatic soul", "", ""}, + Text{"some liquid essence", "", ""}, + }, { + //ambiguous text + Text{"something wet", "", ""} + }, { + //clear text + Text{"the soul of Barinade", "", ""}} + ); + + hintTable[RHT_BONGO_BONGO_SOUL] = HintText::Item({ + //obscure text + Text{"a shadowy soul", "", ""}, + Text{"some handy essence", "", ""}, + }, { + //ambiguous text + Text{"something dark", "", ""} + }, { + //clear text + Text{"the soul of Bongo Bongo", "", ""}} + ); + + hintTable[RHT_TWINROVA_SOUL] = HintText::Item({ + //obscure text + Text{"old souls", "", ""}, + Text{"twin essences", "", ""}, + }, { + //ambiguous text + Text{"something spiritual", "", ""} + }, { + //clear text + Text{"the soul of Twinrova", "", ""}} + ); + + hintTable[RHT_GANON_SOUL] = HintText::Item({ + //obscure text + Text{"an evil soul", "", ""}, + Text{"some powerful essence", "", ""}, + }, { + //ambiguous text + Text{"something strong", "", ""} + }, { + //clear text + Text{"the soul of Ganon", "", ""}} + ); + hintTable[RHT_EPONA] = HintText::Item({ //obscure text Text{"a horse", /*french*/"un fidèle destrier", /*spanish*/"una yegua"}, diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 6a3c4d744..46d039f9b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -829,6 +829,30 @@ void GenerateItemPool() { ctx->PlaceItemInLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD, RG_HUGE_RUPEE, false, true); } + if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS)) { + AddItemToMainPool(RG_GOHMA_SOUL); + AddItemToMainPool(RG_KING_DODONGO_SOUL); + AddItemToMainPool(RG_BARINADE_SOUL); + AddItemToMainPool(RG_PHANTOM_GANON_SOUL); + AddItemToMainPool(RG_VOLVAGIA_SOUL); + AddItemToMainPool(RG_MORPHA_SOUL); + AddItemToMainPool(RG_BONGO_BONGO_SOUL); + AddItemToMainPool(RG_TWINROVA_SOUL); + + ctx->possibleIceTrapModels.push_back(RG_GOHMA_SOUL); + ctx->possibleIceTrapModels.push_back(RG_KING_DODONGO_SOUL); + ctx->possibleIceTrapModels.push_back(RG_BARINADE_SOUL); + ctx->possibleIceTrapModels.push_back(RG_PHANTOM_GANON_SOUL); + ctx->possibleIceTrapModels.push_back(RG_VOLVAGIA_SOUL); + ctx->possibleIceTrapModels.push_back(RG_MORPHA_SOUL); + ctx->possibleIceTrapModels.push_back(RG_BONGO_BONGO_SOUL); + ctx->possibleIceTrapModels.push_back(RG_TWINROVA_SOUL); + if (ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).Is(RO_BOSS_SOULS_ON_PLUS_GANON)) { + AddItemToMainPool(RG_GANON_SOUL); + ctx->possibleIceTrapModels.push_back(RG_GANON_SOUL); + } + } + if (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC)) { AddItemToMainPool(RG_PROGRESSIVE_BOMBCHUS, 5); } else { diff --git a/soh/soh/Enhancements/randomizer/3drando/keys.hpp b/soh/soh/Enhancements/randomizer/3drando/keys.hpp new file mode 100644 index 000000000..e69de29bb diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp index fd0fbe6f0..c1bc935a7 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp @@ -254,9 +254,9 @@ void AreaTable_Init_DekuTree() { { // Events EventAccess(&DekuTreeClear, { [] { - return DekuTreeClear || + return DekuTreeClear || (HasBossSoul(RG_GOHMA_SOUL) && (CanJumpslash && (Nuts || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || - HookshotOrBoomerang)); + HookshotOrBoomerang))); }}), }, { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp index ed9502b77..b758be53e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp @@ -294,10 +294,10 @@ void AreaTable_Init_DodongosCavern() { // Events EventAccess(&DodongosCavernClear, { [] { - return DodongosCavernClear || + return DodongosCavernClear || (HasBossSoul(RG_KING_DODONGO_SOUL) && (Here(RR_DODONGOS_CAVERN_BOSS_ROOM, [] { return HasExplosives || (CanUse(RG_MEGATON_HAMMER) && randoCtx->GetTrickOption(RT_DC_HAMMER_FLOOR)); }) && - (Bombs || GoronBracelet) && CanJumpslash); /*todo add chu kill to tricks*/ + (Bombs || GoronBracelet) && CanJumpslash)); /*todo add chu kill to tricks*/ }}), }, { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp index 9b43ecff4..df3ddbbf0 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp @@ -410,7 +410,7 @@ void AreaTable_Init_FireTemple() { { // Events EventAccess(&FireTempleClear, - { [] { return FireTempleClear || (FireTimer >= 64 && CanUse(RG_MEGATON_HAMMER)); }}), + { [] { return FireTempleClear || (HasBossSoul(RG_VOLVAGIA_SOUL) && (FireTimer >= 64 && CanUse(RG_MEGATON_HAMMER))); }}), }, { // Locations diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp index 1f542e0e9..285f759dc 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp @@ -421,8 +421,8 @@ void AreaTable_Init_ForestTemple() { { // Events EventAccess(&ForestTempleClear, { [] { - return ForestTempleClear || ((CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && - (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT))); + return ForestTempleClear || (HasBossSoul(RG_PHANTOM_GANON_SOUL) && ((CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && + (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT)))); } }), }, { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp index 3538b567f..52c4b378b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp @@ -117,7 +117,7 @@ void AreaTable_Init_GanonsCastle() { //Locations LocationAccess(RC_GANONS_TOWER_BOSS_KEY_CHEST, {[]{return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);}}), LocationAccess(RC_GANONDORF_HINT, {[]{return BossKeyGanonsCastle && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD));}}), - LocationAccess(RC_GANON, {[]{return BossKeyGanonsCastle && CanUse(RG_LIGHT_ARROWS) && CanUse(RG_MASTER_SWORD);}}), + LocationAccess(RC_GANON, {[]{return HasBossSoul(RG_GANON_SOUL) && BossKeyGanonsCastle && CanUse(RG_LIGHT_ARROWS) && CanUse(RG_MASTER_SWORD);}}), }, {}); /*--------------------------- diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp index 4ddcbf58f..32bba0660 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp @@ -235,7 +235,7 @@ void AreaTable_Init_JabuJabusBelly() { { // Events //todo: add pot kill trick EventAccess(&JabuJabusBellyClear, - { [] { return JabuJabusBellyClear || (CanUse(RG_BOOMERANG) && CanJumpslash); } }), + { [] { return JabuJabusBellyClear || (HasBossSoul(RG_BARINADE_SOUL) && (CanUse(RG_BOOMERANG) && CanJumpslash)); } }), }, { // Locations diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp index 5b935fe5e..addde6403 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp @@ -195,10 +195,10 @@ void AreaTable_Init_ShadowTemple() { { // Events EventAccess(&ShadowTempleClear, { [] { - return ShadowTempleClear || + return ShadowTempleClear || (HasBossSoul(RG_BONGO_BONGO_SOUL) && ((CanUse(RG_LENS_OF_TRUTH) || randoCtx->GetTrickOption(RT_LENS_BONGO)) && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && - (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || randoCtx->GetTrickOption(RT_SHADOW_BONGO))); + (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || randoCtx->GetTrickOption(RT_SHADOW_BONGO)))); } }), }, { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp index c5ab8348f..35efc3135 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp @@ -259,8 +259,8 @@ void AreaTable_Init_SpiritTemple() { { // Events EventAccess(&SpiritTempleClear, { [] { - return SpiritTempleClear || (CanUse(RG_MIRROR_SHIELD) && - (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD))); + return SpiritTempleClear || (HasBossSoul(RG_TWINROVA_SOUL) && (CanUse(RG_MIRROR_SHIELD) && + (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)))); } }), }, { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp index 8b50289e1..75255a4d4 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp @@ -319,8 +319,8 @@ void AreaTable_Init_WaterTemple() { { // Events EventAccess(&WaterTempleClear, { [] { - return WaterTempleClear || - (CanUse(RG_HOOKSHOT) && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD))); + return WaterTempleClear || (HasBossSoul(RG_MORPHA_SOUL) && + (CanUse(RG_HOOKSHOT) && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)))); } }), }, { diff --git a/soh/soh/Enhancements/randomizer/3drando/logic.cpp b/soh/soh/Enhancements/randomizer/3drando/logic.cpp index 5e16727b6..3376b1e80 100644 --- a/soh/soh/Enhancements/randomizer/3drando/logic.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/logic.cpp @@ -315,6 +315,16 @@ namespace Logic { uint8_t Age = 0; bool CanCompleteTriforce = false; + bool CanSummonGohma = false; + bool CanSummonKingDodongo = false; + bool CanSummonBarinade = false; + bool CanSummonPhantomGanon = false; + bool CanSummonVolvagia = false; + bool CanSummonMorpha = false; + bool CanSummonBongoBongo = false; + bool CanSummonTwinrova = false; + bool CanSummonGanon = false; + //Events bool ShowedMidoSwordAndShield = false; bool CarpenterRescue = false; @@ -466,6 +476,35 @@ namespace Logic { (age == HasProjectileAge::Either && (Slingshot || Boomerang || Hookshot || Bow)); } + bool HasBossSoul(RandomizerGet itemName) { + auto ctx = Rando::Context::GetInstance(); + if (!ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS)) { + return true; + } + switch(itemName) { + case RG_GOHMA_SOUL: + return CanSummonGohma; break; + case RG_KING_DODONGO_SOUL: + return CanSummonKingDodongo; break; + case RG_BARINADE_SOUL: + return CanSummonBarinade; break; + case RG_PHANTOM_GANON_SOUL: + return CanSummonPhantomGanon; break; + case RG_VOLVAGIA_SOUL: + return CanSummonVolvagia; break; + case RG_MORPHA_SOUL: + return CanSummonMorpha; break; + case RG_BONGO_BONGO_SOUL: + return CanSummonBongoBongo; break; + case RG_TWINROVA_SOUL: + return CanSummonTwinrova; break; + case RG_GANON_SOUL: + return ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).Is(RO_BOSS_SOULS_ON_PLUS_GANON) ? CanSummonGanon : true; + break; + default: break; + } + } + uint8_t GetDifficultyValueFromString(Rando::Option& glitchOption) { return 0; } @@ -892,6 +931,17 @@ namespace Logic { //Triforce Pieces TriforcePieces = 0; + //Boss Souls + CanSummonGohma = false; + CanSummonKingDodongo = false; + CanSummonBarinade = false; + CanSummonPhantomGanon = false; + CanSummonVolvagia = false; + CanSummonMorpha = false; + CanSummonBongoBongo = false; + CanSummonTwinrova = false; + CanSummonGanon = false; + //Drops and Bottle Contents Access DekuNutDrop = false; NutPot = false; diff --git a/soh/soh/Enhancements/randomizer/3drando/logic.hpp b/soh/soh/Enhancements/randomizer/3drando/logic.hpp index ad7639732..4452b3715 100644 --- a/soh/soh/Enhancements/randomizer/3drando/logic.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/logic.hpp @@ -307,6 +307,16 @@ extern bool LinksCow; extern uint8_t Age; extern bool CanCompleteTriforce; +extern bool CanSummonGohma; +extern bool CanSummonKingDodongo; +extern bool CanSummonBarinade; +extern bool CanSummonPhantomGanon; +extern bool CanSummonVolvagia; +extern bool CanSummonMorpha; +extern bool CanSummonBongoBongo; +extern bool CanSummonTwinrova; +extern bool CanSummonGanon; + // Events extern bool ShowedMidoSwordAndShield; extern bool CarpenterRescue; @@ -371,6 +381,7 @@ void UpdateHelpers(); bool CanPlay(bool song); bool CanUse(RandomizerGet itemName); bool HasProjectile(HasProjectileAge age); +bool HasBossSoul(RandomizerGet itemName); bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount); bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched); bool CanDoGlitch(GlitchType glitch); diff --git a/soh/soh/Enhancements/randomizer/3drando/shops.cpp b/soh/soh/Enhancements/randomizer/3drando/shops.cpp index cd2c8004d..8e2206966 100644 --- a/soh/soh/Enhancements/randomizer/3drando/shops.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/shops.cpp @@ -10,7 +10,7 @@ std::vector NonShopItems = {}; -static std::array, 0xE1> trickNameTable; // Table of trick names for ice traps +static std::array, 0xF0> trickNameTable; // Table of trick names for ice traps bool initTrickNames = false; //Indicates if trick ice trap names have been initialized yet //Set vanilla shop item locations before potentially shuffling @@ -703,6 +703,42 @@ void InitTrickNames() { Text{"Piece of Cheese", "Morceau de Fromage", "Piece of Cheese"}, Text{"Triforce Shard", "Éclat de Triforce", "Triforce Shard"}, Text{"Shiny Rock", "Caiiloux Brillant", "Shiny Rock"}}; + trickNameTable[RG_GOHMA_SOUL] = { + Text{"Spider Sense", "", ""}, + Text{"Deku Spirit", "", ""}, + Text("Ghost of Ghoma", "", "")}; + trickNameTable[RG_KING_DODONGO_SOUL] = { + Text{"Lizard Soul", "", ""}, + Text{"Regal Remains", "", ""}, + Text{"Dodongo's Core", "", ""}}; + trickNameTable[RG_BARINADE_SOUL] = { + Text{"Parasitic Poltergeist", "", ""}, + Text{"Jabu Insides", "", ""}, + Text{"Barinade Bacteria", "", ""}}; + trickNameTable[RG_PHANTOM_GANON_SOUL] = { + Text{"Bigger Poe", "", ""}, + Text{"Sacred Forest Pine Tree", "", ""}, + Text{"Ganon's Phantom", "", ""}}; + trickNameTable[RG_VOLVAGIA_SOUL] = { + Text{"Dragon Roast", "", ""}, + Text{"Hot n' Ready", "", ""}, + Text{"Volvagia's Vitality", "", ""}}; + trickNameTable[RG_MORPHA_SOUL] = { + Text{"Dihydrogen Monoxide", "", ""}, + Text{"Morpha Molecules", "", ""}, + Text{"Wet Stuff", "", ""}}; + trickNameTable[RG_BONGO_BONGO_SOUL] = { + Text{"Shadow Soul", "", ""}, + Text{"Dark Essence", "", ""}, + Text{"Bongo Bongo's Bongo", "", ""}}; + trickNameTable[RG_TWINROVA_SOUL] = { + Text{"Sandy Ashes", "", ""}, + Text{"Spiritual Spirit", "", ""}, + Text{"Twin Rovers", "", ""}}; + trickNameTable[RG_GANON_SOUL] = { + Text{"Pure Evil", "", ""}, + Text{"Ganon's Ghost", "", ""}, + Text{"Pork", "", ""}}; /* //Names for individual upgrades, in case progressive names are replaced diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 950af1634..6c6a4fd55 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -10,6 +10,7 @@ #include "objects/object_gi_key/object_gi_key.h" #include "objects/object_gi_bosskey/object_gi_bosskey.h" #include "objects/object_gi_hearts/object_gi_hearts.h" +#include "objects/object_gi_fire/object_gi_fire.h" #include "objects/object_toki_objects/object_toki_objects.h" #include "objects/gameplay_field_keep/gameplay_field_keep.h" #include "soh_assets.h" @@ -277,3 +278,52 @@ extern "C" void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry get } CLOSE_DISPS(play->state.gfxCtx); } + +extern "C" void Randomizer_DrawBossSoul(PlayState* play, GetItemEntry* getItemEntry) { + s16 slot = getItemEntry->getItemId - RG_GOHMA_SOUL; + s16 flameColors[9][3] = { + { 0, 255, 0 }, // Gohma + { 255, 0, 100 }, // King Dodongo + { 50, 255, 255}, // Barinade + { 4, 195, 46 }, // Phantom Ganon + { 237, 95, 95 }, // Volvagia + { 85, 180, 223 }, // Morpha + { 126, 16, 177 }, // Bongo Bongo + { 222, 158, 47 }, // Twinrova + { 80, 80, 80 }, // Ganon/Dorf + }; + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + if (slot == 8) { // For Ganon only... + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 0, 0, 0, 255); + } else { + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 255); + } + gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gBossSoulSkullDL); + + if (slot >= 0) { + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + gSPSegment(POLY_XLU_DISP++, 8, (uintptr_t)Gfx_TwoTexScroll( + play->state.gfxCtx, 0, 0 * (play->state.frames * 0), + 0 * (play->state.frames * 0), 16, 32, 1, 1 * (play->state.frames * 1), + -1 * (play->state.frames * 8), 16, 32 + )); + Matrix_Push(); + Matrix_Translate(0.0f, -70.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(5.0f, 5.0f, 5.0f, MTXMODE_APPLY); + Matrix_ReplaceRotation(&play->billboardMtxF); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + gDPSetGrayscaleColor(POLY_XLU_DISP++, flameColors[slot][0], flameColors[slot][1], flameColors[slot][2], 255); + gSPGrayscale(POLY_XLU_DISP++, true); + gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiBlueFireFlameDL); + gSPGrayscale(POLY_XLU_DISP++, false); + Matrix_Pop(); + } + + CLOSE_DISPS(play->state.gfxCtx); + +} diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index 2ec521766..dcf146c28 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -12,6 +12,7 @@ extern "C" { void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawBossSoul(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawMasterSword(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawTriforcePiece(PlayState* play, GetItemEntry getItemEntry); diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index c7df99e04..e2311cdf7 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -94,26 +94,26 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem des Geistes" }, ITEMTYPE_SONG, 0xBE, true, &Logic::RequiemOfSpirit, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Präludium des Lichts" }, ITEMTYPE_SONG, 0xC0, true, &Logic::PreludeOfLight, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); // Maps and Compasses - itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, &Logic::noVariable, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, &Logic::noVariable, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, &Logic::noVariable, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Waldtempel Karte" }, ITEMTYPE_MAP, 0xA8, false, &Logic::noVariable, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Feuertempel Karte" }, ITEMTYPE_MAP, 0xA9, false, &Logic::noVariable, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Wassertempel-Karte" }, ITEMTYPE_MAP, 0xAA, false, &Logic::noVariable, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Geistertempel Karte" }, ITEMTYPE_MAP, 0xAB, false, &Logic::noVariable, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, &Logic::noVariable, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Boden des Brunnens Karte" }, ITEMTYPE_MAP, 0xAD, false, &Logic::noVariable, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Eishöhle Karte" }, ITEMTYPE_MAP, 0xAE, false, &Logic::noVariable, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompass des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, &Logic::noVariable, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompass der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, &Logic::noVariable, RHT_DODONGOS_CAVERN_COMPASS,RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompass des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, &Logic::noVariable, RHT_JABU_JABUS_BELLY_COMPASS,RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Waldtempel-Kompass" }, ITEMTYPE_COMPASS, 0x9E, false, &Logic::noVariable, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Feuertempel-Kompass" }, ITEMTYPE_COMPASS, 0x9F, false, &Logic::noVariable, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Wassertempel-Kompass" }, ITEMTYPE_COMPASS, 0xA0, false, &Logic::noVariable, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Geistiger Tempelkompass" }, ITEMTYPE_COMPASS, 0xA1, false, &Logic::noVariable, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompass des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, &Logic::noVariable, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Boden des Brunnenkompasses" }, ITEMTYPE_COMPASS, 0xA3, false, &Logic::noVariable, RHT_BOTTOM_OF_THE_WELL_COMPASS,RG_BOTTOM_OF_THE_WELL_COMPASS,OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Eishöhlenkompass" }, ITEMTYPE_COMPASS, 0xA4, false, &Logic::noVariable, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, &Logic::noVariable, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, &Logic::noVariable, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, &Logic::noVariable, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Waldtempel Karte" }, ITEMTYPE_MAP, 0xA8, false, &Logic::noVariable, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Feuertempel Karte" }, ITEMTYPE_MAP, 0xA9, false, &Logic::noVariable, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Wassertempel-Karte" }, ITEMTYPE_MAP, 0xAA, false, &Logic::noVariable, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Geistertempel Karte" }, ITEMTYPE_MAP, 0xAB, false, &Logic::noVariable, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, &Logic::noVariable, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Boden des Brunnens Karte" }, ITEMTYPE_MAP, 0xAD, false, &Logic::noVariable, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Eishöhle Karte" }, ITEMTYPE_MAP, 0xAE, false, &Logic::noVariable, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompass des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, &Logic::noVariable, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompass der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, &Logic::noVariable, RHT_DODONGOS_CAVERN_COMPASS,RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompass des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, &Logic::noVariable, RHT_JABU_JABUS_BELLY_COMPASS,RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Waldtempel-Kompass" }, ITEMTYPE_COMPASS, 0x9E, false, &Logic::noVariable, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Feuertempel-Kompass" }, ITEMTYPE_COMPASS, 0x9F, false, &Logic::noVariable, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Wassertempel-Kompass" }, ITEMTYPE_COMPASS, 0xA0, false, &Logic::noVariable, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Geistiger Tempelkompass" }, ITEMTYPE_COMPASS, 0xA1, false, &Logic::noVariable, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompass des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, &Logic::noVariable, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Boden des Brunnenkompasses" }, ITEMTYPE_COMPASS, 0xA3, false, &Logic::noVariable, RHT_BOTTOM_OF_THE_WELL_COMPASS,RG_BOTTOM_OF_THE_WELL_COMPASS,OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Eishöhlenkompass" }, ITEMTYPE_COMPASS, 0xA4, false, &Logic::noVariable, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); // Boss Keys itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Waldtempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x95, true, &Logic::BossKeyForestTemple, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_FOREST_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); @@ -240,6 +240,25 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_BUY_RED_POTION_40] = Item(RG_BUY_RED_POTION_40, Text{ "Buy Red Potion [40]", "Acheter: Potion Rouge [40]", "Rotes Elixier kaufen [40]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, &Logic::noVariable, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 40); itemTable[RG_BUY_RED_POTION_50] = Item(RG_BUY_RED_POTION_50, Text{ "Buy Red Potion [50]", "Acheter: Potion Rouge [50]", "Rotes Elixier kaufen [50]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, &Logic::noVariable, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); // Misc. + itemTable[RG_GOHMA_SOUL] = Item(RG_GOHMA_SOUL, Text{ "Gohma's Soul", "", "" }, ITEMTYPE_ITEM, 0xE0, true, &Logic::CanSummonGohma, RHT_GOHMA_SOUL, RG_GOHMA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GOHMA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); + itemTable[RG_KING_DODONGO_SOUL] = Item(RG_KING_DODONGO_SOUL, Text{ "King Dodongo's Soul", "", "" }, ITEMTYPE_ITEM, 0xE1, true, &Logic::CanSummonKingDodongo,RHT_KING_DODONGO_SOUL, RG_KING_DODONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_KING_DODONGO_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); + itemTable[RG_BARINADE_SOUL] = Item(RG_BARINADE_SOUL, Text{ "Barinade's Soul", "", "" }, ITEMTYPE_ITEM, 0xE2, true, &Logic::CanSummonBarinade, RHT_BARINADE_SOUL, RG_BARINADE_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BARINADE_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); + itemTable[RG_PHANTOM_GANON_SOUL] = Item(RG_PHANTOM_GANON_SOUL, Text{ "Phantom Ganon's Soul", "", "" }, ITEMTYPE_ITEM, 0xE3, true, &Logic::CanSummonPhantomGanon,RHT_PHANTOM_GANON_SOUL, RG_PHANTOM_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_PHANTOM_GANON_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); + itemTable[RG_VOLVAGIA_SOUL] = Item(RG_VOLVAGIA_SOUL, Text{ "Volvagia's Soul", "", "" }, ITEMTYPE_ITEM, 0xE4, true, &Logic::CanSummonVolvagia, RHT_VOLVAGIA_SOUL, RG_VOLVAGIA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_VOLVAGIA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); + itemTable[RG_MORPHA_SOUL] = Item(RG_MORPHA_SOUL, Text{ "Morpha's Soul", "", "" }, ITEMTYPE_ITEM, 0xE5, true, &Logic::CanSummonMorpha, RHT_MORPHA_SOUL, RG_MORPHA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MORPHA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); + itemTable[RG_BONGO_BONGO_SOUL] = Item(RG_BONGO_BONGO_SOUL, Text{ "Bongo Bongo's Soul", "", "" }, ITEMTYPE_ITEM, 0xE6, true, &Logic::CanSummonBongoBongo, RHT_BONGO_BONGO_SOUL, RG_BONGO_BONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BONGO_BONGO_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); + itemTable[RG_TWINROVA_SOUL] = Item(RG_TWINROVA_SOUL, Text{ "Twinrova's Soul", "", "" }, ITEMTYPE_ITEM, 0xE7, true, &Logic::CanSummonTwinrova, RHT_TWINROVA_SOUL, RG_TWINROVA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_TWINROVA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); + itemTable[RG_GANON_SOUL] = Item(RG_GANON_SOUL, Text{ "Ganon's Soul", "", "" }, ITEMTYPE_ITEM, 0xE8, true, &Logic::CanSummonGanon, RHT_GANON_SOUL, RG_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GANON_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); + itemTable[RG_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, &Logic::noVariable, RHT_NONE); itemTable[RG_HINT] = Item(RG_HINT, Text{ "Hint", "Indice", "Hinweis" }, ITEMTYPE_EVENT, RG_HINT, false, &Logic::noVariable, RHT_NONE); // Individual stages of progressive items (only here for GetItemEntry purposes, not for use in seed gen) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 3ca43436c..11e260cbe 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1695,6 +1695,7 @@ void GenerateRandomizerImgui(std::string seed = "") { cvarSettings[RSK_SHUFFLE_MAGIC_BEANS] = CVarGetInteger("gRandomizeShuffleBeans", 0); cvarSettings[RSK_SHUFFLE_MERCHANTS] = CVarGetInteger("gRandomizeShuffleMerchants", RO_SHUFFLE_MERCHANTS_OFF); cvarSettings[RSK_SHUFFLE_100_GS_REWARD] = CVarGetInteger("gRandomizeShuffle100GSReward", RO_GENERIC_OFF); + cvarSettings[RSK_SHUFFLE_BOSS_SOULS] = CVarGetInteger("gRandomizeShuffleBossSouls", RO_BOSS_SOULS_OFF); cvarSettings[RSK_ENABLE_BOMBCHU_DROPS] = CVarGetInteger("gRandomizeEnableBombchuDrops", 0); cvarSettings[RSK_BOMBCHUS_IN_LOGIC] = CVarGetInteger("gRandomizeBombchusInLogic", 0); cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVarGetInteger("gRandomizeSkipChildZelda", 0); @@ -1926,6 +1927,7 @@ void RandomizerSettingsWindow::DrawElement() { static const char* randoTokensanity[4] = { "Off", "Dungeons", "Overworld", "All Tokens" }; static const char* randoShuffleScrubs[4] = { "Off", "Affordable", "Expensive", "Random Prices" }; static const char* randoShuffleMerchants[3] = { "Off", "On (no hints)", "On (with hints)" }; + static const char* randoShuffleBossSouls[3] = { "Off", "On", "On + Ganon"}; // Shuffle Dungeon Items Settings static const char* randoShuffleMapsAndCompasses[6] = { "Start With", "Vanilla", "Own Dungeon", @@ -2844,6 +2846,15 @@ void RandomizerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(); + // Shuffle Boss Souls + // Forces players to find a boss's soul before defeating them in their lair. + ImGui::Text("%s", ctx->GetOption(RSK_SHUFFLE_BOSS_SOULS).GetName().c_str()); + UIWidgets::InsertHelpHoverText("Shuffles 8 boss souls (one for each blue warp dungeon). A boss will not appear until you collect its respective soul." + "\n\"On + Ganon\" will also hide Ganon and Ganondorf behind a boss soul."); + UIWidgets::EnhancementCombobox("gRandomizeShuffleBossSouls", randoShuffleBossSouls, RO_BOSS_SOULS_OFF); + + UIWidgets::PaddedSeparator(); + ImGui::PopItemWidth(); ImGui::EndChild(); @@ -4725,7 +4736,7 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { void Randomizer::CreateCustomMessages() { // RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED // with GIMESSAGE(getItemID, itemID, english, german, french). - const std::array getItemMessages = {{ + const std::array getItemMessages = {{ GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON, "You found %gGreg%w!", "%gGreg%w! Du hast ihn wirklich gefunden!", @@ -4959,7 +4970,18 @@ void Randomizer::CreateCustomMessages() { GIMESSAGE(RG_TYCOON_WALLET, ITEM_WALLET_GIANT, "You got a %rTycoon's Wallet%w!&It's gigantic! Now you can carry&up to %y999 rupees%w!", "Du erhältst die %rGoldene&Geldbörse%w! Die größte aller&Geldbörsen! Jetzt kannst Du bis&zu %y999 Rubine%w mit dir führen!", - "Vous obtenez la %rBourse de Magnat%w!&Elle peut contenir jusqu'à %y999 rubis%w!&C'est gigantesque!") + "Vous obtenez la %rBourse de Magnat%w!&Elle peut contenir jusqu'à %y999 rubis%w!&C'est gigantesque!"), + + GIMESSAGE_UNTRANSLATED(RG_GOHMA_SOUL, ITEM_BIG_POE, "You found the soul for %gGohma%w!"), + GIMESSAGE_UNTRANSLATED(RG_KING_DODONGO_SOUL, ITEM_BIG_POE, "You found the soul for %rKing&Dodongo%w!"), + GIMESSAGE_UNTRANSLATED(RG_BARINADE_SOUL, ITEM_BIG_POE, "You found the soul for %bBarinade%w!"), + GIMESSAGE_UNTRANSLATED(RG_PHANTOM_GANON_SOUL, ITEM_BIG_POE, "You found the soul for %gPhantom&Ganon%w!"), + GIMESSAGE_UNTRANSLATED(RG_VOLVAGIA_SOUL, ITEM_BIG_POE, "You found the soul for %rVolvagia%w!"), + GIMESSAGE_UNTRANSLATED(RG_MORPHA_SOUL, ITEM_BIG_POE, "You found the soul for %bMorpha%w!"), + GIMESSAGE_UNTRANSLATED(RG_BONGO_BONGO_SOUL, ITEM_BIG_POE, "You found the soul for %pBongo&Bongo%w!"), + GIMESSAGE_UNTRANSLATED(RG_TWINROVA_SOUL, ITEM_BIG_POE, "You found the soul for %yTwinrova%w!"), + GIMESSAGE_UNTRANSLATED(RG_GANON_SOUL, ITEM_BIG_POE, "You found the soul for %cGanon%w!"), + }}; CreateGetItemMessages(&getItemMessages); CreateRupeeMessages(); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 02652a83d..26464522c 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1814,6 +1814,15 @@ typedef enum { RG_BUY_RED_POTION_50, RG_TRIFORCE, RG_TRIFORCE_PIECE, + RG_GOHMA_SOUL, + RG_KING_DODONGO_SOUL, + RG_BARINADE_SOUL, + RG_PHANTOM_GANON_SOUL, + RG_VOLVAGIA_SOUL, + RG_MORPHA_SOUL, + RG_BONGO_BONGO_SOUL, + RG_TWINROVA_SOUL, + RG_GANON_SOUL, RG_HINT, RG_TYCOON_WALLET, RG_FAIRY_OCARINA, @@ -3018,6 +3027,15 @@ typedef enum { RHT_DEKU_STICK_CAPACITY_20, RHT_DEKU_STICK_CAPACITY_30, RHT_TRIFORCE_PIECE, + RHT_GOHMA_SOUL, + RHT_KING_DODONGO_SOUL, + RHT_BARINADE_SOUL, + RHT_PHANTOM_GANON_SOUL, + RHT_VOLVAGIA_SOUL, + RHT_MORPHA_SOUL, + RHT_BONGO_BONGO_SOUL, + RHT_TWINROVA_SOUL, + RHT_GANON_SOUL, RHT_EPONA, // Entrances RHT_DESERT_COLOSSUS_TO_COLOSSUS_GROTTO, @@ -3427,6 +3445,7 @@ typedef enum { RSK_TRIFORCE_HUNT, RSK_TRIFORCE_HUNT_PIECES_TOTAL, RSK_TRIFORCE_HUNT_PIECES_REQUIRED, + RSK_SHUFFLE_BOSS_SOULS, RSK_MAX } RandomizerSettingKey; @@ -3551,6 +3570,12 @@ typedef enum { RO_AMMO_DROPS_OFF, } RandoOptionAmmoDrops; +typedef enum { + RO_BOSS_SOULS_OFF, + RO_BOSS_SOULS_ON, + RO_BOSS_SOULS_ON_PLUS_GANON, +} RandoOptionBossSouls; + //Any Dungeon Item (start with, vanilla, own dungeon, any dungeon, //overworld, anywhere) typedef enum { diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 33c206b47..d7e0c1dfe 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -160,6 +160,16 @@ typedef enum { RAND_INF_ADULT_FISHING, RAND_INF_10_BIG_POES, + RAND_INF_GOHMA_SOUL, + RAND_INF_KING_DODONGO_SOUL, + RAND_INF_BARINADE_SOUL, + RAND_INF_PHANTOM_GANON_SOUL, + RAND_INF_VOLVAGIA_SOUL, + RAND_INF_MORPHA_SOUL, + RAND_INF_BONGO_BONGO_SOUL, + RAND_INF_TWINROVA_SOUL, + RAND_INF_GANON_SOUL, + // If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16) RAND_INF_MAX, diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index f24ab818b..e5e633e74 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -84,6 +84,20 @@ std::vector triforcePieces = { ITEM_TRACKER_ITEM(RG_TRIFORCE_PIECE, 0, DrawItem), }; +std::vector bossSoulItems = { + //Hack for right now, just gonna draw souls as bottles/big poes. + //Will replace with other macro once we have a custom texture + ITEM_TRACKER_ITEM_CUSTOM(RG_GOHMA_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ), + ITEM_TRACKER_ITEM_CUSTOM(RG_KING_DODONGO_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ), + ITEM_TRACKER_ITEM_CUSTOM(RG_BARINADE_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ), + ITEM_TRACKER_ITEM_CUSTOM(RG_PHANTOM_GANON_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ), + ITEM_TRACKER_ITEM_CUSTOM(RG_VOLVAGIA_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ), + ITEM_TRACKER_ITEM_CUSTOM(RG_MORPHA_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ), + ITEM_TRACKER_ITEM_CUSTOM(RG_BONGO_BONGO_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ), + ITEM_TRACKER_ITEM_CUSTOM(RG_TWINROVA_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ), + ITEM_TRACKER_ITEM_CUSTOM(RG_GANON_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ), +}; + std::vector itemTrackerDungeonsWithMapsHorizontal = { { SCENE_DEKU_TREE, { ITEM_DUNGEON_MAP, ITEM_COMPASS } }, { SCENE_DODONGOS_CAVERN, { ITEM_DUNGEON_MAP, ITEM_COMPASS } }, @@ -154,6 +168,18 @@ std::map itemTrackerDungeonShortNames = { { SCENE_THIEVES_HIDEOUT, "HIDE" }, }; +std::map itemTrackerBossShortNames = { + { RG_GOHMA_SOUL, "GOHMA" }, + { RG_KING_DODONGO_SOUL, "KD" }, + { RG_BARINADE_SOUL, "BARI" }, + { RG_PHANTOM_GANON_SOUL, "PG"}, + { RG_VOLVAGIA_SOUL, "VOLV"}, + { RG_MORPHA_SOUL, "MORPH"}, + { RG_BONGO_BONGO_SOUL, "BONGO"}, + { RG_TWINROVA_SOUL, "TWIN"}, + { RG_GANON_SOUL, "GANON"}, +}; + std::vector dungeonItems = {}; std::unordered_map actualItemTrackerItemMap = { @@ -609,6 +635,53 @@ void DrawItem(ItemTrackerItem item) { hasItem = IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT); itemName = "Triforce Piece"; break; + case RG_GOHMA_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_GOHMA_SOUL); + itemName = "Gohma's Soul"; + break; + case RG_KING_DODONGO_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_KING_DODONGO_SOUL); + itemName = "King Dodongo's Soul"; + break; + case RG_BARINADE_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_BARINADE_SOUL); + itemName = "Barinade's Soul"; + break; + case RG_PHANTOM_GANON_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_PHANTOM_GANON_SOUL); + itemName = "Phantom Ganon's Soul"; + break; + case RG_VOLVAGIA_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_VOLVAGIA_SOUL); + itemName = "Volvagia's Soul"; + break; + case RG_MORPHA_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_MORPHA_SOUL); + itemName = "Morpha's Soul"; + break; + case RG_BONGO_BONGO_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_BONGO_BONGO_SOUL); + itemName = "Bongo Bongo's Soul"; + break; + case RG_TWINROVA_SOUL: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_TWINROVA_SOUL); + itemName = "Twinrova's Soul"; + break; + case RG_GANON_SOUL: + actualItemId = item.id; + hasItem = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_BOSS_SOULS) == RO_BOSS_SOULS_ON_PLUS_GANON ? + Flags_GetRandomizerInf(RAND_INF_GANON_SOUL) : true; + + itemName = "Ganon's Soul"; + break; } if (GameInteractor::IsSaveLoaded() && (hasItem && item.id != actualItemId && actualItemTrackerItemMap.find(actualItemId) != actualItemTrackerItemMap.end())) { @@ -621,6 +694,16 @@ void DrawItem(ItemTrackerItem item) { ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); DrawItemCount(item); + + if (item.id >= RG_GOHMA_SOUL && item.id <= RG_GANON_SOUL) { + ImVec2 p = ImGui::GetCursorScreenPos(); + std::string bossName = itemTrackerBossShortNames[item.id]; + ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(bossName.c_str()).x / 2), p.y - (iconSize + 13))); + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL_WHITE); + ImGui::Text("%s", bossName.c_str()); + ImGui::PopStyleColor(); + } + ImGui::EndGroup(); if (itemName == "") { @@ -956,6 +1039,17 @@ void UpdateVectors() { mainWindowItems.insert(mainWindowItems.end(), triforcePieces.begin(), triforcePieces.end()); } + //If we're adding boss souls to the main window... + if (CVarGetInteger("gItemTrackerBossSoulsDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) { + //...add empty items on the main window to get the souls on their own row. (Too many to sit with Greg/Triforce pieces) + while (mainWindowItems.size() % 6) { + mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); + } + + //Add boss souls + mainWindowItems.insert(mainWindowItems.end(), bossSoulItems.begin(), bossSoulItems.end()); + } + shouldUpdateVectors = false; } @@ -1056,6 +1150,12 @@ void ItemTrackerWindow::DrawElement() { EndFloatingWindows(); } + if (CVarGetInteger("gItemTrackerBossSoulsDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) { + BeginFloatingWindows("Boss Soul Tracker"); + DrawItemsInRows(bossSoulItems); + EndFloatingWindows(); + } + if (CVarGetInteger("gItemTrackerNotesDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE && CVarGetInteger("gItemTrackerDisplayType", TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { ImGui::SetNextWindowSize(ImVec2(400,300), ImGuiCond_FirstUseEver); BeginFloatingWindows("Personal Notes", ImGuiWindowFlags_NoFocusOnAppearing); @@ -1195,6 +1295,10 @@ void ItemTrackerSettingsWindow::DrawElement() { shouldUpdateVectors = true; } + if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Boss Souls", "gItemTrackerBossSoulsDisplayType", displayTypes, SECTION_DISPLAY_HIDDEN)) { + shouldUpdateVectors = true; + } + if (CVarGetInteger("gItemTrackerDisplayType", TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) { if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Personal notes", "gItemTrackerNotesDisplayType", displayTypes, SECTION_DISPLAY_HIDDEN)) { shouldUpdateVectors = true; diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h index 1fb4e1063..8a0b754a8 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h @@ -24,6 +24,11 @@ bool HasEquipment(ItemTrackerItem); id, #id, #id "_Faded", data, drawFunc \ } +#define ITEM_TRACKER_ITEM_CUSTOM(id, name, nameFaded, data, drawFunc)\ + { \ + id, #name, #nameFaded "_Faded", data, drawFunc \ + } + typedef struct ItemTrackerDungeon { uint32_t id; std::vector items; diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 12deeba6b..ec4595f01 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -106,6 +106,7 @@ void Settings::CreateOptions() { mOptions[RSK_SHUFFLE_ADULT_TRADE] = Option::Bool("Shuffle Adult Trade"); mOptions[RSK_SHUFFLE_CHEST_MINIGAME] = Option::U8("Shuffle Chest Minigame", {"Off", "On (Separate)", "On (Pack)"}); mOptions[RSK_SHUFFLE_100_GS_REWARD] = Option::Bool("Shuffle 100 GS Reward"); + mOptions[RSK_SHUFFLE_BOSS_SOULS] = Option::U8("Shuffle Boss Souls", {"Off", "On", "On + Ganon"}); mOptions[RSK_SHUFFLE_MAPANDCOMPASS] = Option::U8("Maps/Compasses", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); mOptions[RSK_KEYSANITY] = Option::U8("Small Keys", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); mOptions[RSK_GERUDO_KEYS] = Option::U8("Gerudo Fortress Keys", {"Vanilla", "Any Dungeon", "Overworld", "Anywhere"}); @@ -616,6 +617,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_ADULT_TRADE], &mOptions[RSK_SHUFFLE_CHEST_MINIGAME], &mOptions[RSK_SHUFFLE_100_GS_REWARD], + &mOptions[RSK_SHUFFLE_BOSS_SOULS], }); mOptionGroups[RSG_SHUFFLE_DUNGEON_ITEMS] = OptionGroup("Shuffle Dungeon Items", { &mOptions[RSK_SHUFFLE_MAPANDCOMPASS], @@ -821,6 +823,7 @@ void Settings::CreateOptions() { { "Shuffle Settings:Shuffle Frog Song Rupees", RSK_SHUFFLE_FROG_SONG_RUPEES }, { "Shuffle Settings:Shuffle Merchants", RSK_SHUFFLE_MERCHANTS }, { "Shuffle Settings:Shuffle 100 GS Reward", RSK_SHUFFLE_100_GS_REWARD }, + { "Shuffle Settings:Shuffle Boss Souls", RSK_SHUFFLE_BOSS_SOULS }, { "Start with Deku Shield", RSK_STARTING_DEKU_SHIELD }, { "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD }, { "Start with Fairy Ocarina", RSK_STARTING_OCARINA }, @@ -1520,6 +1523,14 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { mOptions[index].SetSelectedIndex(RO_AMMO_DROPS_OFF); } break; + case RSK_SHUFFLE_BOSS_SOULS: + if (it.value() == "Off") { + mOptions[index].SetSelectedIndex(RO_BOSS_SOULS_OFF); + } else if (it.value() == "On") { + mOptions[index].SetSelectedIndex(RO_BOSS_SOULS_ON); + } else if (it.value() == "On + Ganon") { + mOptions[index].SetSelectedIndex(RO_BOSS_SOULS_ON_PLUS_GANON); + } case RSK_STARTING_OCARINA: if (it.value() == "Off") { mOptions[index].SetSelectedIndex(RO_STARTING_OCARINA_OFF); diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index ec25d2062..73c8aebd1 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2611,6 +2611,13 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { return Return_Item_Entry(giEntry, RG_NONE); } + if (item >= RG_GOHMA_SOUL && item <= RG_GANON_SOUL) { + u8 index = item - RG_GOHMA_SOUL; + Flags_SetRandomizerInf(RAND_INF_GOHMA_SOUL + index); + + return Return_Item_Entry(giEntry, RG_NONE); + } + if (item == RG_PROGRESSIVE_BOMBCHUS) { if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) { INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU; diff --git a/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c b/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c index ee62b141e..ca0d5d948 100644 --- a/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c +++ b/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c @@ -652,6 +652,9 @@ void BossVa_Init(Actor* thisx, PlayState* play2) { this->actor.colChkInfo.damageTable = sDamageTable; sPhase2Timer = 0xFFFF; if (Flags_GetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE)) { + if (Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_SOULS) && !Flags_GetRandomizerInf(RAND_INF_BARINADE_SOUL)) { + sCsState = BOSSVA_BATTLE; + } else { sCsState = INTRO_CALL_BARI; sDoorState = 100; func_8002DF54(play, &this->actor, 1); @@ -682,6 +685,7 @@ void BossVa_Init(Actor* thisx, PlayState* play2) { } sCameraAtMaxVel = sCameraEyeMaxVel = sZeroVec; + } } else { sCsState = INTRO_START; diff --git a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c index 7125984e2..dc19f2d7d 100644 --- a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c +++ b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c @@ -495,7 +495,7 @@ void DemoEffect_Init(Actor* thisx, PlayState* play2) { this->jewel.type = DEMO_EFFECT_JEWEL_ZORA; this->jewel.isPositionInit = 0; DemoEffect_InitJewel(play, this); - Actor_ChangeCategory(play, &play->actorCtx, &this->actor, ACTOR_EN_DOOR); + Actor_ChangeCategory(play, &play->actorCtx, &this->actor, ACTORCAT_BOSS); if ((play->sceneNum == SCENE_JABU_JABU) && (Flags_GetInfTable(INFTABLE_145))) { Actor_Kill(&this->actor); return;