diff --git a/soh/assets/custom/objects/gameplay_keep/gPlayerAnim_link_rocs_feather_jump b/soh/assets/custom/objects/gameplay_keep/gPlayerAnim_link_rocs_feather_jump new file mode 100644 index 00000000000..331911d025b Binary files /dev/null and b/soh/assets/custom/objects/gameplay_keep/gPlayerAnim_link_rocs_feather_jump differ diff --git a/soh/assets/custom/objects/gameplay_keep/gPlayerAnim_link_rocs_feather_jump_Data b/soh/assets/custom/objects/gameplay_keep/gPlayerAnim_link_rocs_feather_jump_Data new file mode 100644 index 00000000000..e739fd7b146 Binary files /dev/null and b/soh/assets/custom/objects/gameplay_keep/gPlayerAnim_link_rocs_feather_jump_Data differ diff --git a/soh/assets/custom/objects/object_rocs_feather/eff_unknown_12.i8 b/soh/assets/custom/objects/object_rocs_feather/eff_unknown_12.i8 new file mode 100644 index 00000000000..e305f366839 Binary files /dev/null and b/soh/assets/custom/objects/object_rocs_feather/eff_unknown_12.i8 differ diff --git a/soh/assets/custom/objects/object_rocs_feather/eff_unknown_12_i8 b/soh/assets/custom/objects/object_rocs_feather/eff_unknown_12_i8 new file mode 100644 index 00000000000..e305f366839 Binary files /dev/null and b/soh/assets/custom/objects/object_rocs_feather/eff_unknown_12_i8 differ diff --git a/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL b/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL new file mode 100644 index 00000000000..2e1d14239bb --- /dev/null +++ b/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_tri_0 b/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_tri_0 new file mode 100644 index 00000000000..94927832fce --- /dev/null +++ b/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_tri_0 @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_tri_1 b/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_tri_1 new file mode 100644 index 00000000000..9ab8f972b93 --- /dev/null +++ b/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_tri_1 @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_vtx_0 b/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_vtx_0 new file mode 100644 index 00000000000..6b168144985 --- /dev/null +++ b/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_vtx_0 @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_vtx_1 b/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_vtx_1 new file mode 100644 index 00000000000..44ab971573e --- /dev/null +++ b/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_vtx_1 @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_vtx_cull b/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_vtx_cull new file mode 100644 index 00000000000..e43cf3bda13 --- /dev/null +++ b/soh/assets/custom/objects/object_rocs_feather/gGiRocsFeatherDL_vtx_cull @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_rocs_feather/mat_gGiRocsFeatherDL_feather_feather b/soh/assets/custom/objects/object_rocs_feather/mat_gGiRocsFeatherDL_feather_feather new file mode 100644 index 00000000000..e21e92ff897 --- /dev/null +++ b/soh/assets/custom/objects/object_rocs_feather/mat_gGiRocsFeatherDL_feather_feather @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_rocs_feather/mat_gGiRocsFeatherDL_feather_stem b/soh/assets/custom/objects/object_rocs_feather/mat_gGiRocsFeatherDL_feather_stem new file mode 100644 index 00000000000..b523babf20d --- /dev/null +++ b/soh/assets/custom/objects/object_rocs_feather/mat_gGiRocsFeatherDL_feather_stem @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_rocs_feather/model.xml b/soh/assets/custom/objects/object_rocs_feather/model.xml new file mode 100644 index 00000000000..5d798a1ab9a --- /dev/null +++ b/soh/assets/custom/objects/object_rocs_feather/model.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/textures/icon_item_static/gRocsFeatherTex.rgba32.png b/soh/assets/custom/textures/icon_item_static/gRocsFeatherTex.rgba32.png new file mode 100644 index 00000000000..b2e4f99da1d Binary files /dev/null and b/soh/assets/custom/textures/icon_item_static/gRocsFeatherTex.rgba32.png differ diff --git a/soh/assets/custom/textures/item_name_static/gRocsFeatherItemNameENGTex.ia4.png b/soh/assets/custom/textures/item_name_static/gRocsFeatherItemNameENGTex.ia4.png new file mode 100644 index 00000000000..bc72f3ced5b Binary files /dev/null and b/soh/assets/custom/textures/item_name_static/gRocsFeatherItemNameENGTex.ia4.png differ diff --git a/soh/assets/custom/textures/item_name_static/gRocsFeatherItemNameFRATex.ia4.png b/soh/assets/custom/textures/item_name_static/gRocsFeatherItemNameFRATex.ia4.png new file mode 100644 index 00000000000..dc42bdc072d Binary files /dev/null and b/soh/assets/custom/textures/item_name_static/gRocsFeatherItemNameFRATex.ia4.png differ diff --git a/soh/assets/custom/textures/item_name_static/gRocsFeatherItemNameGERTex.ia4.png b/soh/assets/custom/textures/item_name_static/gRocsFeatherItemNameGERTex.ia4.png new file mode 100644 index 00000000000..5842acfeb59 Binary files /dev/null and b/soh/assets/custom/textures/item_name_static/gRocsFeatherItemNameGERTex.ia4.png differ diff --git a/soh/assets/soh_assets.h b/soh/assets/soh_assets.h index 3c3ddcf5a7e..f973abd132d 100644 --- a/soh/assets/soh_assets.h +++ b/soh/assets/soh_assets.h @@ -348,6 +348,9 @@ static const ALIGN_ASSET(2) char gKeyringKeysGanonsCastleMQDL[] = dgKeyringKeysG #define dgHouseKeyDL "__OTR__objects/object_housekey/gHouseKeyDL" static const ALIGN_ASSET(2) char gHouseKeyDL[] = dgHouseKeyDL; +#define dgGiRocsFeatherDL "__OTR__objects/object_rocs_feather/gGiRocsFeatherDL" +static const ALIGN_ASSET(2) char gGiRocsFeatherDL[] = dgGiRocsFeatherDL; + // overlays #define dgOptionsDividerChangeLangVtx "__OTR__overlays/ovl_file_choose/gOptionsDividerChangeLangVtx" static const ALIGN_ASSET(2) char gOptionsDividerChangeLangVtx[] = dgOptionsDividerChangeLangVtx; @@ -431,6 +434,18 @@ static const ALIGN_ASSET(2) char gFileSelLanguageFRATex[] = dgFileSelLanguageFRA #define dgFileSelLanguageGERTex "__OTR__textures/title_static/gFileSelLanguageGERTex" static const ALIGN_ASSET(2) char gFileSelLanguageGERTex[] = dgFileSelLanguageGERTex; +#define dgRocsFeatherTex "__OTR__textures/icon_item_static/gRocsFeatherTex" +static const ALIGN_ASSET(2) char gRocsFeatherTex[] = dgRocsFeatherTex; + +#define dgRocsFeatherItemNameENGTex "__OTR__textures/item_name_static/gRocsFeatherItemNameENGTex" +static const ALIGN_ASSET(2) char gRocsFeatherItemNameENGTex[] = dgRocsFeatherItemNameENGTex; + +#define dgRocsFeatherItemNameGERTex "__OTR__textures/item_name_static/gRocsFeatherItemNameGERTex" +static const ALIGN_ASSET(2) char gRocsFeatherItemNameGERTex[] = dgRocsFeatherItemNameGERTex; + +#define dgRocsFeatherItemNameFRATex "__OTR__textures/item_name_static/gRocsFeatherItemNameFRATex" +static const ALIGN_ASSET(2) char gRocsFeatherItemNameFRATex[] = dgRocsFeatherItemNameFRATex; + #define dgEmptyTexture "__OTR__textures/virtual/gEmptyTexture" static const ALIGN_ASSET(2) char gEmptyTexture[] = dgEmptyTexture; @@ -453,6 +468,10 @@ static const ALIGN_ASSET(2) char gLinkAdultGoronTunicSkel[] = dgLinkAdultGoronTu #define dgLinkAdultZoraTunicSkel "__OTR__objects/object_link_boy_zora/gLinkAdultZoraTunicSkel" static const ALIGN_ASSET(2) char gLinkAdultZoraTunicSkel[] = dgLinkAdultZoraTunicSkel; +// Animations +#define dgPlayerAnim_link_rocs_feather_jump "__OTR__objects/gameplay_keep/gPlayerAnim_link_rocs_feather_jump" +static const ALIGN_ASSET(2) char gPlayerAnim_link_rocs_feather_jump[] = dgPlayerAnim_link_rocs_feather_jump; + // LUS Logo #define dgShipLogoDL "__OTR__textures/nintendo_rogo_static/gShipLogoDL" static const ALIGN_ASSET(2) char gShipLogoDL[] = dgShipLogoDL; diff --git a/soh/include/functions.h b/soh/include/functions.h index 11dbf8c811a..f9e7650f4a3 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -2452,11 +2452,13 @@ void Font_LoadOrderedFontNTSC(Font* font); // #endregion // #region SOH [General] - void Interface_RandoRestoreSwordless(void); s32 Ship_CalcShouldDrawAndUpdate(PlayState* play, Actor* actor, Vec3f* projectedPos, f32 projectedW, bool* shouldDraw, bool* shouldUpdate); +// #region SOH [Rocs Feather] +void func_80838940(Player* this, LinkAnimationHeader* anim, f32 arg2, PlayState* play, u16 sfxId); + // #endregion #ifdef __cplusplus diff --git a/soh/include/variables.h b/soh/include/variables.h index 27ad4584d24..e296017aab3 100644 --- a/soh/include/variables.h +++ b/soh/include/variables.h @@ -103,7 +103,7 @@ extern "C" extern u16 gUpgradeCapacities[8][4]; extern u32 gGsFlagsMasks[4]; extern u32 gGsFlagsShifts[4]; - extern void* gItemIcons[0x82]; + extern void* gItemIcons[157]; extern u8 gItemAgeReqs[]; extern u8 gSlotAgeReqs[]; extern u8 gItemSlots[56]; diff --git a/soh/include/z64item.h b/soh/include/z64item.h index b1fa897fe6e..9bbb8bb30f2 100644 --- a/soh/include/z64item.h +++ b/soh/include/z64item.h @@ -309,6 +309,7 @@ typedef enum { /* 0x99 */ ITEM_STICK_UPGRADE_30, /* 0x9A */ ITEM_NUT_UPGRADE_30, /* 0x9B */ ITEM_NUT_UPGRADE_40, + /* */ ITEM_ROCS_FEATHER, /* 0xFC */ ITEM_LAST_USED = 0xFC, /* 0xFE */ ITEM_NONE_FE = 0xFE, /* 0xFF */ ITEM_NONE = 0xFF @@ -592,6 +593,7 @@ typedef enum { /* 0x7A */ GID_SONG_TIME, /* 0x7B */ GID_SONG_STORM, /* 0x7C */ GID_TRIFORCE_PIECE, + /* 0x7C */ GID_ROCS_FEATHER, /* */ GID_FISHING_POLE, /* 0x7C */ GID_MAXIMUM diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index ff40f149a02..6a1e619d462 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -394,7 +394,7 @@ static bool GiveItemHandler(std::shared_ptr Console, const std::v if (args[1].compare("vanilla") == 0) { getItemEntry = ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, std::stoi(args[2])); } else if (args[1].compare("randomizer") == 0) { - getItemEntry = ItemTableManager::Instance->RetrieveItemEntry(MOD_RANDOMIZER, std::stoi(args[2])); + getItemEntry = Rando::StaticData::RetrieveItem((RandomizerGet)std::stoi(args[2])).GetGIEntry_Copy(); } else { ERROR_MESSAGE("[SOH] Invalid argument passed, must be 'vanilla' or 'randomizer'"); return 1; diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 463f900e0d4..7f6e7512283 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -433,7 +433,16 @@ void DrawInventoryTab() { uint8_t item = gSaveContext.inventory.items[index]; PushStyleButton(Colors::DarkGray); - if (item != ITEM_NONE) { + if (item == ITEM_ROCS_FEATHER) { + auto ret = ImGui::ImageButton( + "ROCS_FEATHER", + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("ROCS_FEATHER"), + ImVec2(48.0f, 48.0f), ImVec2(0, 0), ImVec2(1, 1)); + if (ret) { + selectedIndex = index; + ImGui::OpenPopup(itemPopupPicker); + } + } else if (item != ITEM_NONE) { const ItemMapEntry& slotEntry = itemMapping.find(item)->second; auto ret = ImGui::ImageButton( slotEntry.name.c_str(), @@ -1736,4 +1745,6 @@ void SaveEditorWindow::DrawElement() { } void SaveEditorWindow::InitElement() { + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ROCS_FEATHER", gRocsFeatherTex, + ImVec4(1, 1, 1, 1)); } diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index f604c9c7954..a2c30b46de1 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -2382,6 +2382,22 @@ typedef enum { // - `*Color_RGB8` VB_APPLY_TUNIC_COLOR, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*int32_t` // ItemID + VB_USE_ITEM, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*int16_t` // pauseCtx->namedItem + VB_DRAW_CUSTOM_ITEM_NAME, + } GIVanillaBehavior; #endif 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 c74c0ff23b9..170c726265c 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 @@ -1964,6 +1964,16 @@ void StaticData::HintTable_Init_Item() { CustomMessage("a gold fragment", /*german*/"ein Goldfragment", /*french*/"un fragment d'or")}); // /*spanish*/un fragmento dorado + hintTextTable[RHT_ROCS_FEATHER] = HintText(CustomMessage("Roc's Feather", /*german*/"Roc's Feather", /*french*/"Roc's Feather"), + // /*spanish*/un fragmento de la Trifuerza + {}, { + CustomMessage("a feather", /*german*/"a feather", /*french*/"a feather"), + // /*spanish*/un trígono del triunfo + CustomMessage("a chicken wing", /*german*/"a chicken wing", /*french*/"a chicken wing"), + // /*spanish*/un porción de queso + CustomMessage("a blue wing", /*german*/"a blue wing", /*french*/"a blue wing")}); + // /*spanish*/un fragmento dorado + hintTextTable[RHT_GOHMA_SOUL] = HintText(CustomMessage("the soul of Gohma", /*german*/"Gohmas Seele", /*french*/"l'Âme de Gohma"), { CustomMessage("something webbed", /*german*/"etwas Verwobenes", /*french*/"un truc entoilé") diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index ec90b0619a8..0ddf13ed7ff 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -511,6 +511,14 @@ void GenerateItemPool() { ctx->PlaceItemInLocation(RC_GANON, RG_TRIFORCE); // Win condition } + if (ctx->GetOption(RSK_ROCS_FEATHER)) { + ctx->possibleIceTrapModels.push_back(RG_ROCS_FEATHER); + AddItemToMainPool(RG_ROCS_FEATHER); + if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) { + AddItemToPool(PendingJunkPool, RG_ROCS_FEATHER); + } + } + // Fixed item locations ctx->PlaceItemInLocation(RC_HC_ZELDAS_LETTER, RG_ZELDAS_LETTER); diff --git a/soh/soh/Enhancements/randomizer/3drando/shops.cpp b/soh/soh/Enhancements/randomizer/3drando/shops.cpp index 06fe5790f83..0c0ce66abe8 100644 --- a/soh/soh/Enhancements/randomizer/3drando/shops.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/shops.cpp @@ -27,7 +27,7 @@ PriceSettingsStruct::PriceSettingsStruct(RandomizerSettingKey _main, RandomizerS affordable = _affordable; } -static std::array, 0xF1> trickNameTable; // Table of trick names for ice traps +static std::array, RG_MAX> 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 @@ -887,6 +887,11 @@ void InitTrickNames() { Text{ "Triforce Shard", "Éclat de Triforce", "Triforce-Fragment" }, // "Triforce Shard" Text{ "Shiny Rock", "Caillou Brillant", "glänzender Stein" }, // "Shiny Rock" }; + trickNameTable[RG_ROCS_FEATHER] = { + Text{ "Chicken Wing", "Chicken Wing", "Chicken Wing" }, // "Chicken Wing" + Text{ "Roc's Leg", "Roc's Leg", "Roc's Leg" }, // "Roc's Leg" + Text{ "Roc's Fapper", "Roc's Fapper", "Roc's Fapper" }, // "Roc's Fapper" + }; trickNameTable[RG_GOHMA_SOUL] = { Text{ "Spider Sense", "Sens de l'Araignée", "Spinnensinn" }, Text{ "Deku Spirit", "Parasite Mojo", "Deku Geist" }, @@ -1159,7 +1164,7 @@ void InitTrickNames() { } // Generate a fake name for the ice trap based on the item it's displayed as -Text GetIceTrapName(uint8_t id) { +Text GetIceTrapName(uint16_t id) { // If the trick names table has not been initialized, do so if (!initTrickNames) { InitTrickNames(); diff --git a/soh/soh/Enhancements/randomizer/3drando/shops.hpp b/soh/soh/Enhancements/randomizer/3drando/shops.hpp index 81c4a43582b..799856b6301 100644 --- a/soh/soh/Enhancements/randomizer/3drando/shops.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/shops.hpp @@ -27,4 +27,4 @@ extern std::vector GetMinVanillaShopItems(int total_replaced); extern uint16_t GetRandomPrice(Rando::Location* loc, PriceSettingsStruct priceSettings); extern uint16_t GetCheapBalancedPrice(); extern int GetShopsanityReplaceAmount(); -extern Text GetIceTrapName(uint8_t id); +extern Text GetIceTrapName(uint16_t id); diff --git a/soh/soh/Enhancements/randomizer/RocsFeather.cpp b/soh/soh/Enhancements/randomizer/RocsFeather.cpp new file mode 100644 index 00000000000..fecb2489e10 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/RocsFeather.cpp @@ -0,0 +1,100 @@ +#include +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" +#include + +extern "C" { +#include +#include "functions.h" +#include "variables.h" +#include "macros.h" +#include "objects/gameplay_keep/gameplay_keep.h" +extern PlayState* gPlayState; +} + +#define MAX_ROCS_USES 1 + +static uint8_t rocsUseCount = 0; +static uint8_t groundTimer = 0; +static f32 effectsScale = 1.0f; + +void RegisterRocsFeather() { + bool shouldRegister = IS_RANDO && RAND_GET_OPTION(RSK_ROCS_FEATHER); + + COND_HOOK(OnPlayerUpdate, shouldRegister, []() { + Player* player = GET_PLAYER(gPlayState); + + // Reset Rocs count when touching the ground for 3+ frames + if (player->actor.bgCheckFlags & 1) { + if (groundTimer <= 3) { + groundTimer++; + } + } else { + groundTimer = 0; + } + + if (groundTimer >= 3) { + rocsUseCount = 0; + } + }); + + COND_VB_SHOULD(VB_USE_ITEM, shouldRegister, { + int32_t* usedItem = va_arg(args, int32_t*); + Player* player = GET_PLAYER(gPlayState); + + // Roc's Feather behaviour + if (*usedItem == ITEM_ROCS_FEATHER) { + *should = false; + + if (rocsUseCount < MAX_ROCS_USES) { + rocsUseCount++; + + func_80838940(player, (LinkAnimationHeader*)&gPlayerAnim_link_rocs_feather_jump, 5.8f, gPlayState, 0); + + // Actionvar needed to prevent weird animation morph + player->av2.actionVar2 = 1; + + // Move player forward on Roc's use + player->linearVelocity = 5.0f; + player->actor.world.rot.y = player->yaw = player->actor.shape.rot.y; + + if (gSaveContext.linkAge == LINK_AGE_CHILD) { + player->actor.velocity.y = 7.0f; + effectsScale = 1.0f; + } else { + player->actor.velocity.y = 7.5f; + effectsScale = 1.5f; + } + + Vec3f effectsPos = player->actor.home.pos; + effectsPos.y += 3; + + EffectSsGRipple_Spawn(gPlayState, &effectsPos, 200 * effectsScale, 300 * effectsScale, 1); + EffectSsGSplash_Spawn(gPlayState, &effectsPos, NULL, NULL, 0, 150 * effectsScale); + + // Remove hopping state when using Roc's after sidehop/backflip to allow grabbing ledges again + player->stateFlags2 &= ~(PLAYER_STATE2_HOPPING); + + Player_PlaySfx(&player->actor, NA_SE_PL_SKIP); + } + } + }); + + COND_VB_SHOULD(VB_DRAW_CUSTOM_ITEM_NAME, shouldRegister, { + u32 namedItem = va_arg(args, u32); + if (namedItem == ITEM_ROCS_FEATHER) { + *should = true; + const char* textureName = gRocsFeatherItemNameENGTex; + + if (gSaveContext.language == LANGUAGE_GER) { + textureName = gRocsFeatherItemNameGERTex; + } else if (gSaveContext.language == LANGUAGE_FRA) { + textureName = gRocsFeatherItemNameFRATex; + } + + memcpy(gPlayState->pauseCtx.nameSegment, textureName, strlen(textureName) + 1); + } + }); +} + +static RegisterShipInitFunc registerRocsFeather(RegisterRocsFeather, { "IS_RANDO" }); diff --git a/soh/soh/Enhancements/randomizer/RocsFeatherCycle.c b/soh/soh/Enhancements/randomizer/RocsFeatherCycle.c new file mode 100644 index 00000000000..31dfb903040 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/RocsFeatherCycle.c @@ -0,0 +1,25 @@ +#include "soh/Enhancements/randomizer/RocsFeatherCycle.h" +#include "functions.h" +#include "variables.h" +#include "macros.h" + +uint8_t Enhancement_GetNextNayrusItem() { + if (INV_CONTENT(ITEM_NAYRUS_LOVE) == ITEM_NAYRUS_LOVE && Flags_GetRandomizerInf(RAND_INF_OBTAINED_ROCS_FEATHER)) { + return ITEM_ROCS_FEATHER; + } + if (INV_CONTENT(ITEM_NAYRUS_LOVE) == ITEM_ROCS_FEATHER && Flags_GetRandomizerInf(RAND_INF_OBTAINED_NAYRUS_LOVE)) { + return ITEM_NAYRUS_LOVE; + } + return ITEM_NONE; +} + +uint8_t Enhancement_GetPrevNayrusItem() { + if (INV_CONTENT(ITEM_NAYRUS_LOVE) == ITEM_NAYRUS_LOVE && Flags_GetRandomizerInf(RAND_INF_OBTAINED_ROCS_FEATHER)) { + return ITEM_ROCS_FEATHER; + } + if (INV_CONTENT(ITEM_NAYRUS_LOVE) == ITEM_ROCS_FEATHER && Flags_GetRandomizerInf(RAND_INF_OBTAINED_NAYRUS_LOVE)) { + return ITEM_NAYRUS_LOVE; + } + + return ITEM_NONE; +} diff --git a/soh/soh/Enhancements/randomizer/RocsFeatherCycle.h b/soh/soh/Enhancements/randomizer/RocsFeatherCycle.h new file mode 100644 index 00000000000..859cb5ab6fa --- /dev/null +++ b/soh/soh/Enhancements/randomizer/RocsFeatherCycle.h @@ -0,0 +1,9 @@ +#ifndef ROCS_FEATHER_H +#define ROCS_FEATHER_H + +#include + +uint8_t Enhancement_GetNextNayrusItem(); +uint8_t Enhancement_GetPrevNayrusItem(); + +#endif diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 7d266d78bef..dd709a65e91 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -489,6 +489,21 @@ extern "C" void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry* getIte CLOSE_DISPS(play->state.gfxCtx); } +extern "C" void Randomizer_DrawRocsFeather(PlayState* play, GetItemEntry* getItemEntry) { + Color_RGB8 color = { 0, 60, 100 }; + + 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); + + gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiRocsFeatherDL); + + CLOSE_DISPS(play->state.gfxCtx); +} + Gfx* GetEmptyDlist(GraphicsContext* gfxCtx) { Gfx* dListHead; Gfx* dList; diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index 8483a7bf966..ca50cf7e127 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -27,6 +27,7 @@ void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBombchuBagInLogic(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBombchuBag(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawOverworldKey(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawRocsFeather(PlayState* play, GetItemEntry* getItemEntry); #define GET_ITEM_MYSTERY \ { \ diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 9aa9b140096..4ab27394398 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -403,6 +403,8 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_MAGIC_SINGLE] = Item(RG_MAGIC_SINGLE, Text{ "Magic Meter", "Jauge de Magie", "Magische Kraft" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_SINGLE, RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verb. Magische Kraft" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce-Splitter" }, ITEMTYPE_ITEM, 0xDF, true, LOGIC_TRIFORCE_PIECES, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_ROCS_FEATHER] = Item(RG_ROCS_FEATHER, Text{ "Roc's Feather", "Roc's Feather", "Roc's Feather" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_ROCS_FEATHER, RHT_ROCS_FEATHER, RG_ROCS_FEATHER, OBJECT_GI_BOMB_2, GID_ROCS_FEATHER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_ROCS_FEATHER].SetCustomDrawFunc(Randomizer_DrawRocsFeather); // clang-format on diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 1f6b71a881a..03d02089d06 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -762,6 +762,9 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_SUNLIGHT_ARROWS] = "Light Arrows can be used to light up the sun switches instead of using the Mirror Shield. " "Item placement logic will respect this option, so it might be required to use this to progress."; + mOptionDescriptions[RSK_ROCS_FEATHER] = + "Adds Roc's Feather to the item pool. Roc's Feather is a custom item granting the player a jump on demand. " + "The jump can also be used when already in mid-air. Roc's Feather is not considered by logic."; mOptionDescriptions[RSK_SLINGBOW_BREAK_BEEHIVES] = "Allows Slingshot and Bow to break beehives when Beehive Shuffle is turned on."; mOptionDescriptions[RSK_LOGIC_RULES] = diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index de17327f19b..5c8e457de00 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -65,6 +65,7 @@ const std::string Randomizer::triforcePieceMessageTableID = "RandomizerTriforceP const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi"; const std::string Randomizer::IceTrapRandoMessageTableID = "RandomizerIceTrap"; const std::string Randomizer::randoMiscHintsTableID = "RandomizerMiscHints"; +const std::string Randomizer::RocsFeatherMessageTableID = "RandomizerRocsFeather"; static const char* englishRupeeNames[188] = { "[P]", @@ -980,7 +981,13 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe case RG_FARORES_WIND: return INV_CONTENT(ITEM_FARORES_WIND) == ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; case RG_NAYRUS_LOVE: - return INV_CONTENT(ITEM_NAYRUS_LOVE) == ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + if (!GetRandoSettingValue(RSK_ROCS_FEATHER)) { + return INV_CONTENT(ITEM_NAYRUS_LOVE) == ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + } else { + return Flags_GetRandomizerInf(RAND_INF_OBTAINED_NAYRUS_LOVE) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN; + } + case RG_ROCS_FEATHER: + return Flags_GetRandomizerInf(RAND_INF_OBTAINED_ROCS_FEATHER) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN; // Bottles case RG_EMPTY_BOTTLE: @@ -4904,6 +4911,22 @@ CustomMessage Randomizer::GetTriforcePieceMessage() { return messageEntry; } +void CreateRocsFeatherMessage() { + CustomMessage RocsFeatherMessage = { + { "You found %cRoc's Feather%w!", "You found %cRoc's Feather%w!", "You found %cRoc's Feather%w!" }, + }; + CustomMessageManager* customMessageManager = CustomMessageManager::Instance; + customMessageManager->AddCustomMessageTable(Randomizer::RocsFeatherMessageTableID); + customMessageManager->CreateMessage(Randomizer::RocsFeatherMessageTableID, 0, RocsFeatherMessage); +} + +CustomMessage Randomizer::GetRocsFeatherMessage() { + CustomMessage messageEntry = + CustomMessageManager::Instance->RetrieveMessage(Randomizer::RocsFeatherMessageTableID, 0); + messageEntry.Format(); + return messageEntry; +} + void CreateNaviRandoMessages() { CustomMessage NaviMessages[NUM_NAVI_MESSAGES] = { @@ -5882,6 +5905,7 @@ void Randomizer::CreateCustomMessages() { } }; CreateGetItemMessages(getItemMessages); CreateRupeeMessages(); + CreateRocsFeatherMessage(); CreateTriforcePieceMessages(); CreateNaviRandoMessages(); CreateFireTempleGoronMessages(); @@ -6318,6 +6342,12 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { INV_CONTENT(ITEM_NUT) = ITEM_NUT; AMMO(ITEM_NUT) = static_cast(CUR_CAPACITY(UPG_NUTS)); break; + case RG_ROCS_FEATHER: + Flags_SetRandomizerInf(RAND_INF_OBTAINED_ROCS_FEATHER); + if (INV_CONTENT(ITEM_NAYRUS_LOVE) == ITEM_NONE) { + INV_CONTENT(ITEM_NAYRUS_LOVE) = ITEM_ROCS_FEATHER; + } + break; default: LUSLOG_WARN("Randomizer_Item_Give didn't have behaviour specified for getItemId=%d", item); assert(false); diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 54c85307b6f..30e5f2c0dcd 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -38,6 +38,7 @@ class Randomizer { static const std::string NaviRandoMessageTableID; static const std::string IceTrapRandoMessageTableID; static const std::string randoMiscHintsTableID; + static const std::string RocsFeatherMessageTableID; static Sprite* GetSeedTexture(uint8_t index); bool SpoilerFileExists(const char* spoilerFileName); @@ -75,6 +76,7 @@ class Randomizer { static CustomMessage GetRupeeMessage(u16 rupeeTextId); static CustomMessage GetIceTrapMessage(); static CustomMessage GetTriforcePieceMessage(); + static CustomMessage GetRocsFeatherMessage(); }; #ifdef __cplusplus diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 02bffe53ed8..dca6faa9ef5 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -210,6 +210,7 @@ typedef enum { LOGIC_OCARINA_C_LEFT_BUTTON, LOGIC_OCARINA_C_RIGHT_BUTTON, LOGIC_TRIFORCE_PIECES, + LOGIC_ROCS_FEATHER, LOGIC_CAN_BORROW_MASKS, LOGIC_BORROW_SKULL_MASK, LOGIC_BORROW_SPOOKY_MASK, @@ -4333,6 +4334,10 @@ typedef enum { RG_BACK_TOWER_KEY, RG_HYLIA_LAB_KEY, RG_FISHING_HOLE_KEY, + + // Custom Items + RG_ROCS_FEATHER, + // Logic Only RG_DISTANT_SCARECROW, RG_STICKS, @@ -5454,6 +5459,7 @@ typedef enum { RHT_DEKU_STICK_CAPACITY_20, RHT_DEKU_STICK_CAPACITY_30, RHT_TRIFORCE_PIECE, + RHT_ROCS_FEATHER, RHT_GOHMA_SOUL, RHT_KING_DODONGO_SOUL, RHT_BARINADE_SOUL, @@ -6238,6 +6244,7 @@ typedef enum { RSK_SHUFFLE_SONG_FAIRIES, RSK_LOCK_OVERWORLD_DOORS, RSK_SHUFFLE_GRASS, + RSK_ROCS_FEATHER, RSK_MAX } RandomizerSettingKey; diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 8742805a6f2..b566e8ee5c9 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -2016,4 +2016,6 @@ DEFINE_RAND_INF(RAND_INF_DEKU_TREE_QUEEN_GOHMA_GRASS_6) DEFINE_RAND_INF(RAND_INF_DEKU_TREE_QUEEN_GOHMA_GRASS_7) DEFINE_RAND_INF(RAND_INF_DEKU_TREE_QUEEN_GOHMA_GRASS_8) // End Grass -DEFINE_RAND_INF(RAND_INF_OBTAINED_RUTOS_LETTER) \ No newline at end of file +DEFINE_RAND_INF(RAND_INF_OBTAINED_RUTOS_LETTER) +DEFINE_RAND_INF(RAND_INF_OBTAINED_NAYRUS_LOVE) +DEFINE_RAND_INF(RAND_INF_OBTAINED_ROCS_FEATHER) diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index cd32cc4b144..49646997ff4 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -136,6 +136,10 @@ std::vector triforcePieces = { ITEM_TRACKER_ITEM(RG_TRIFORCE_PIECE, 0, DrawItem), }; +std::vector rocsFeather = { + ITEM_TRACKER_ITEM(RG_ROCS_FEATHER, 0, DrawItem), +}; + std::vector bossSoulItems = { ITEM_TRACKER_ITEM(RG_GOHMA_SOUL, 0, DrawItem), ITEM_TRACKER_ITEM(RG_KING_DODONGO_SOUL, 0, DrawItem), ITEM_TRACKER_ITEM(RG_BARINADE_SOUL, 0, DrawItem), ITEM_TRACKER_ITEM(RG_PHANTOM_GANON_SOUL, 0, DrawItem), @@ -809,6 +813,16 @@ void DrawItem(ItemTrackerItem item) { hasItem = IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT); itemName = "Triforce Piece"; break; + case ITEM_NAYRUS_LOVE: + if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_ROCS_FEATHER)) { + hasItem = Flags_GetRandomizerInf(RAND_INF_OBTAINED_NAYRUS_LOVE); + } + break; + case RG_ROCS_FEATHER: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_OBTAINED_ROCS_FEATHER); + itemName = "Roc's Feather"; + break; case RG_GOHMA_SOUL: actualItemId = item.id; hasItem = Flags_GetRandomizerInf(RAND_INF_GOHMA_SOUL); @@ -1404,6 +1418,9 @@ void UpdateVectors() { SECTION_DISPLAY_MAIN_WINDOW) { mainWindowItems.insert(mainWindowItems.end(), dungeonItems.begin(), dungeonItems.end()); } + if (IS_RANDO && RAND_GET_OPTION(RSK_ROCS_FEATHER)) { + mainWindowItems.insert(mainWindowItems.end(), rocsFeather.begin(), rocsFeather.end()); + } // if we're adding greg to the misc window, // and misc isn't on the main window, @@ -2120,4 +2137,9 @@ void RegisterItemTrackerWidgets() { SohGui::mSohMenu->AddSearchWidget({ hookshotIdentWidget, "Randomizer", "Item Tracker", "General Settings" }); } +void RegisterItemTracker() { + COND_HOOK(OnLoadFile, true, [](int32_t fileNum) { shouldUpdateVectors = true; }); +} + +static RegisterShipInitFunc registerItemTracker(RegisterItemTracker); static RegisterMenuInitFunc menuInitFunc(RegisterItemTrackerWidgets); diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 265066a7eb5..1d451dc31b3 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -309,6 +309,7 @@ void Settings::CreateOptions() { // TODO: Compasses show rewards/woth, maps show dungeon mode OPT_BOOL(RSK_BLUE_FIRE_ARROWS, "Blue Fire Arrows", CVAR_RANDOMIZER_SETTING("BlueFireArrows"), mOptionDescriptions[RSK_BLUE_FIRE_ARROWS]); OPT_BOOL(RSK_SUNLIGHT_ARROWS, "Sunlight Arrows", CVAR_RANDOMIZER_SETTING("SunlightArrows"), mOptionDescriptions[RSK_SUNLIGHT_ARROWS]); + OPT_BOOL(RSK_ROCS_FEATHER, "Roc's Feather", CVAR_RANDOMIZER_SETTING("RocsFeather"), mOptionDescriptions[RSK_ROCS_FEATHER]); OPT_U8(RSK_INFINITE_UPGRADES, "Infinite Upgrades", {"Off", "Progressive", "Condensed Progressive"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("InfiniteUpgrades"), mOptionDescriptions[RSK_INFINITE_UPGRADES]); OPT_BOOL(RSK_SKELETON_KEY, "Skeleton Key", CVAR_RANDOMIZER_SETTING("SkeletonKey"), mOptionDescriptions[RSK_SKELETON_KEY]); OPT_BOOL(RSK_SLINGBOW_BREAK_BEEHIVES, "Slingshot/Bow Can Break Beehives", CVAR_RANDOMIZER_SETTING("SlingBowBeehives"), mOptionDescriptions[RSK_SLINGBOW_BREAK_BEEHIVES]); @@ -1423,6 +1424,7 @@ void Settings::CreateOptions() { &mOptions[RSK_ENABLE_BOMBCHU_DROPS], &mOptions[RSK_BLUE_FIRE_ARROWS], &mOptions[RSK_SUNLIGHT_ARROWS], + &mOptions[RSK_ROCS_FEATHER], &mOptions[RSK_INFINITE_UPGRADES], &mOptions[RSK_SKELETON_KEY], &mOptions[RSK_SLINGBOW_BREAK_BEEHIVES], diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 2aadd55d207..77168865112 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2435,6 +2435,8 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { messageEntry = Randomizer::GetIceTrapMessage(); } else if (player->getItemEntry.getItemId == RG_TRIFORCE_PIECE) { messageEntry = Randomizer::GetTriforcePieceMessage(); + } else if (player->getItemEntry.getItemId == RG_ROCS_FEATHER) { + messageEntry = Randomizer::GetRocsFeatherMessage(); } else { messageEntry = Randomizer_GetCustomGetItemMessage(player); } diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 9317f8cbc4e..ead8a06a166 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -1084,6 +1084,9 @@ void SaveManager::InitFileMaxed() { gSaveContext.entranceIndex = ENTR_HYRULE_FIELD_PAST_BRIDGE_SPAWN; gSaveContext.sceneFlags[5].swch = 0x40000000; + + Flags_SetRandomizerInf(RAND_INF_OBTAINED_NAYRUS_LOVE); + Flags_SetRandomizerInf(RAND_INF_OBTAINED_ROCS_FEATHER); } #if defined(__WIIU__) || defined(__SWITCH__) diff --git a/soh/soh/SohGui/ImGuiUtils.cpp b/soh/soh/SohGui/ImGuiUtils.cpp index c80293a53c0..69690ff539d 100644 --- a/soh/soh/SohGui/ImGuiUtils.cpp +++ b/soh/soh/SohGui/ImGuiUtils.cpp @@ -133,11 +133,9 @@ std::map gregMapping = { { ITEM_RUPEE_GREEN, { ITEM_RUPEE_GREEN, "ITEM_RUPEE_GREEN", "ITEM_RUPEE_GREEN_Faded", gRupeeCounterIconTex } } }; -std::map triforcePieceMapping = { - { RG_TRIFORCE_PIECE, { RG_TRIFORCE_PIECE, "RG_TRIFORCE_PIECE", "RG_TRIFORCE_PIECE_Faded", gTriforcePieceTex } } -}; - -std::map bossSoulMapping = { +std::map customItemsMapping = { + { RG_TRIFORCE_PIECE, { RG_TRIFORCE_PIECE, "RG_TRIFORCE_PIECE", "RG_TRIFORCE_PIECE_Faded", gTriforcePieceTex } }, + { RG_ROCS_FEATHER, { RG_ROCS_FEATHER, "RG_ROCS_FEATHER", "RG_ROCS_FEATHER_Faded", gRocsFeatherTex } }, { RG_GOHMA_SOUL, { RG_GOHMA_SOUL, "RG_GOHMA_SOUL", "RG_GOHMA_SOUL_Faded", gBossSoulTex } }, { RG_KING_DODONGO_SOUL, { RG_KING_DODONGO_SOUL, "RG_KING_DODONGO_SOUL", "RG_KING_DODONGO_SOUL_Faded", gBossSoulTex } }, @@ -216,14 +214,7 @@ void RegisterImGuiItemIcons() { entry.second.texturePath, gregFadedGreen); } - for (const auto& entry : triforcePieceMapping) { - Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, - ImVec4(1, 1, 1, 1)); - Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture( - entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f)); - } - - for (const auto& entry : bossSoulMapping) { + for (const auto& entry : customItemsMapping) { Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, ImVec4(1, 1, 1, 1)); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture( diff --git a/soh/soh/SohGui/ImGuiUtils.h b/soh/soh/SohGui/ImGuiUtils.h index 2206b4e481e..a92a1d73753 100644 --- a/soh/soh/SohGui/ImGuiUtils.h +++ b/soh/soh/SohGui/ImGuiUtils.h @@ -36,8 +36,6 @@ typedef struct { // Maps items ids to info for use in ImGui extern std::map itemMapping; -extern std::map gregMapping; - typedef struct { uint32_t id; std::string name; diff --git a/soh/src/code/z_inventory.c b/soh/src/code/z_inventory.c index f2b329ed542..82f087fd099 100644 --- a/soh/src/code/z_inventory.c +++ b/soh/src/code/z_inventory.c @@ -3,6 +3,7 @@ #include "textures/icon_item_static/icon_item_static.h" #include "textures/icon_item_24_static/icon_item_24_static.h" #include "textures/parameter_static/parameter_static.h" +#include // Bit Flag array in which gBitFlags[n] is literally (1 << n) u32 gBitFlags[] = { @@ -168,6 +169,35 @@ void* gItemIcons[] = { gOcarinaBtnIconCLeftTex, gOcarinaBtnIconCRightTex, gOcarinaBtnIconATex, + // Push down array to reach newly added item IDs + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + // Start custom items + gRocsFeatherTex, }; // Used to map item IDs to inventory slots diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 3b1d91f056a..0c880242094 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2463,6 +2463,12 @@ u8 Item_Give(PlayState* play, u8 item) { } } + return Return_Item(item, MOD_NONE, ITEM_NONE); + } else if (item == ITEM_NAYRUS_LOVE && Randomizer_GetSettingValue(RSK_ROCS_FEATHER)) { + Flags_SetRandomizerInf(RAND_INF_OBTAINED_NAYRUS_LOVE); + if (INV_CONTENT(ITEM_NAYRUS_LOVE) == ITEM_NONE) { + INV_CONTENT(ITEM_NAYRUS_LOVE) = ITEM_NAYRUS_LOVE; + } return Return_Item(item, MOD_NONE, ITEM_NONE); } returnItem = gSaveContext.inventory.items[slot]; diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index 89583e5984f..06fbcbf0148 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -594,6 +594,10 @@ void Play_Init(GameState* thisx) { gSlotAgeReqs[SLOT_TRADE_CHILD] = AGE_REQ_CHILD; } + // Handle Rocs Feather requiement + gItemAgeReqs[ITEM_ROCS_FEATHER] = AGE_REQ_NONE; + gSlotAgeReqs[SLOT_NAYRUS_LOVE] = AGE_REQ_NONE; + func_800304DC(play, &play->actorCtx, play->linkActorEntry); while (!func_800973FC(play, &play->roomCtx)) { 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 2de7113d218..1b5b77c3692 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2570,8 +2570,10 @@ void Player_ProcessItemButtons(Player* this, PlayState* play) { sHeldItemButtonIsHeldDown = true; } } else if (GameInteractor_Should(VB_CHANGE_HELD_ITEM_AND_USE_ITEM, true, item)) { - this->heldItemButton = i; - Player_UseItem(play, this, item); + if (GameInteractor_Should(VB_USE_ITEM, true, &item)) { + this->heldItemButton = i; + Player_UseItem(play, this, item); + } } } } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index dad520a0b48..091fad149b4 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -2,6 +2,7 @@ #include "textures/parameter_static/parameter_static.h" #include "textures/icon_item_static/icon_item_static.h" #include "soh/Enhancements/randomizer/ShuffleTradeItems.h" +#include "soh/Enhancements/randomizer/RocsFeatherCycle.h" #include "soh/Enhancements/randomizer/randomizerTypes.h" #include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/cosmetics/cosmeticsTypes.h" @@ -374,6 +375,10 @@ void KaleidoScope_HandleItemCycles(PlayState* play) { KaleidoScope_HandleItemCycleExtras(play, SLOT_TRADE_ADULT, IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE), Randomizer_GetPrevAdultTradeItem(), Randomizer_GetNextAdultTradeItem(), true); + + // Handle Nayru's Love/Roc's Feather + KaleidoScope_HandleItemCycleExtras(play, SLOT_NAYRUS_LOVE, Randomizer_GetSettingValue(RSK_ROCS_FEATHER), + Enhancement_GetPrevNayrusItem(), Enhancement_GetNextNayrusItem(), true); } void KaleidoScope_DrawItemCycles(PlayState* play) { @@ -393,6 +398,10 @@ void KaleidoScope_DrawItemCycles(PlayState* play) { KaleidoScope_DrawItemCycleExtras(play, SLOT_TRADE_ADULT, IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE), Randomizer_GetPrevAdultTradeItem(), Randomizer_GetNextAdultTradeItem()); + + // Draw Nayru's Love/Roc's Feather + KaleidoScope_DrawItemCycleExtras(play, SLOT_NAYRUS_LOVE, Randomizer_GetSettingValue(RSK_ROCS_FEATHER), + Enhancement_GetPrevNayrusItem(), Enhancement_GetNextNayrusItem()); } bool IsItemCycling() { diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 1e53d8180aa..b4cb2d7939c 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -22,6 +22,7 @@ #include "soh/ResourceManagerHelpers.h" #include "soh/SaveManager.h" #include "soh/Enhancements/kaleido.h" +#include static void* sEquipmentFRATexs[] = { gPauseEquipment00FRATex, gPauseEquipment01Tex, gPauseEquipment02Tex, gPauseEquipment03Tex, gPauseEquipment04Tex, @@ -2493,7 +2494,10 @@ void KaleidoScope_UpdateNamePanel(PlayState* play) { osSyncPrintf("J_N=%d point=%d\n", gSaveContext.language, sp2A); const char* textureName = iconNameTextures[sp2A]; - memcpy(pauseCtx->nameSegment, textureName, strlen(textureName) + 1); + + if (!GameInteractor_Should(VB_DRAW_CUSTOM_ITEM_NAME, false, pauseCtx->namedItem)) { + memcpy(pauseCtx->nameSegment, textureName, strlen(textureName) + 1); + } } pauseCtx->nameDisplayTimer = 0;