diff --git a/soh/include/variables.h b/soh/include/variables.h index c7adfe6f42f..ed64357f7f1 100644 --- a/soh/include/variables.h +++ b/soh/include/variables.h @@ -102,7 +102,7 @@ extern "C" extern void* gItemIcons[0x83]; extern u8 gItemAgeReqs[]; extern u8 gSlotAgeReqs[]; - extern u8 gItemSlots[71]; + extern u8 gItemSlots[56]; extern void (*gSceneCmdHandlers[SCENE_CMD_ID_MAX])(PlayState*, SceneCmd*); extern s16 gLinkObjectIds[2]; extern u32 gObjectTableSize; diff --git a/soh/include/z64.h b/soh/include/z64.h index 5cc757fd535..23ffcfb1717 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -914,8 +914,6 @@ typedef struct { /* 0x0266 */ u8 worldMapPoints[20]; // 0 = hidden; 1 = displayed; 2 = highlighted /* 0x027A */ u8 tradeQuestLocation; /* 0x027C */ SkelAnime playerSkelAnime; - Vtx* arrowSelectVtx; - s16 arrowMenuAnimPos; } PauseContext; // size = 0x2C0 typedef enum { diff --git a/soh/include/z64item.h b/soh/include/z64item.h index e126b05d85b..5aa02469afa 100644 --- a/soh/include/z64item.h +++ b/soh/include/z64item.h @@ -116,38 +116,36 @@ typedef enum { } DungeonItem; typedef enum { - /* 0x00 */ SLOT_DINS_FIRE, - /* 0x01 */ SLOT_BOMB, - /* 0x02 */ SLOT_BOMBCHU, - /* 0x03 */ SLOT_NUT, - /* 0x04 */ SLOT_LENS, - /* 0x05 */ SLOT_BEAN, - /* 0x06 */ SLOT_FARORES_WIND, - /* 0x07 */ SLOT_SLINGSHOT, - /* 0x08 */ SLOT_BOOMERANG, - /* 0x09 */ SLOT_STICK, - /* 0x0A */ SLOT_BOOTS_HOVER, - /* 0x0B */ SLOT_TRADE_CHILD, - /* 0x0C */ SLOT_NAYRUS_LOVE, - /* 0x0D */ SLOT_BOW, - /* 0x0E */ SLOT_HOOKSHOT, + /* 0x00 */ SLOT_STICK, + /* 0x01 */ SLOT_NUT, + /* 0x02 */ SLOT_BOMB, + /* 0x03 */ SLOT_BOW, + /* 0x04 */ SLOT_ARROW_FIRE, + /* 0x05 */ SLOT_DINS_FIRE, + /* 0x06 */ SLOT_SLINGSHOT, + /* 0x07 */ SLOT_OCARINA, + /* 0x08 */ SLOT_BOMBCHU, + /* 0x09 */ SLOT_HOOKSHOT, + /* 0x0A */ SLOT_ARROW_ICE, + /* 0x0B */ SLOT_FARORES_WIND, + /* 0x0C */ SLOT_BOOMERANG, + /* 0x0D */ SLOT_LENS, + /* 0x0E */ SLOT_BEAN, /* 0x0F */ SLOT_HAMMER, - /* 0x10 */ SLOT_BOOTS_IRON, - /* 0x11 */ SLOT_TRADE_ADULT, - /* 0x12 */ SLOT_EMPTY_LEFT, - /* 0x13 */ SLOT_BOTTLE_1, - /* 0x14 */ SLOT_BOTTLE_2, - /* 0x15 */ SLOT_BOTTLE_3, - /* 0x16 */ SLOT_BOTTLE_4, - /* 0x17 */ SLOT_EMPTY_RIGHT, - /* 0x18 */ SLOT_OCARINA, - /* 0x19 */ SLOT_ARROW_FIRE, - /* 0x1A */ SLOT_ARROW_ICE, - /* 0x1B */ SLOT_ARROW_LIGHT, - /* 0x1C */ SLOT_TUNIC_KOKIRI, - /* 0x1D */ SLOT_TUNIC_GORON, - /* 0x1E */ SLOT_TUNIC_ZORA, - /* 0x1F */ SLOT_BOOTS_KOKIRI, + /* 0x10 */ SLOT_ARROW_LIGHT, + /* 0x11 */ SLOT_NAYRUS_LOVE, + /* 0x12 */ SLOT_BOTTLE_1, + /* 0x13 */ SLOT_BOTTLE_2, + /* 0x14 */ SLOT_BOTTLE_3, + /* 0x15 */ SLOT_BOTTLE_4, + /* 0x16 */ SLOT_TRADE_ADULT, + /* 0x17 */ SLOT_TRADE_CHILD, + /* 0x18 */ SLOT_TUNIC_KOKIRI, + /* 0x19 */ SLOT_TUNIC_GORON, + /* 0x1A */ SLOT_TUNIC_ZORA, + /* 0x1B */ SLOT_BOOTS_KOKIRI, + /* 0x1C */ SLOT_BOOTS_IRON, + /* 0x1D */ SLOT_BOOTS_HOVER, /* 0xFF */ SLOT_NONE = 0xFF } InventorySlot; diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 2c31fe672e1..c7bee045fc1 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -43,7 +43,7 @@ typedef struct { } ItemEquips; // size = 0x0A typedef struct { - /* 0x00 */ u8 items[28]; + /* 0x00 */ u8 items[24]; /* 0x18 */ s8 ammo[16]; /* 0x28 */ u16 equipment; // a mask where each nibble corresponds to a type of equipment `EquipmentType`, and each bit to an owned piece `EquipInv*` /* 0x2C */ u32 upgrades; @@ -389,7 +389,7 @@ typedef enum { typedef enum { /* 0 */ LINK_AGE_ADULT, - /* 1 */ LINK_AGE_CHILD, + /* 1 */ LINK_AGE_CHILD } LinkAge; diff --git a/soh/soh/Enhancements/boss-rush/BossRush.cpp b/soh/soh/Enhancements/boss-rush/BossRush.cpp index c109df4104c..e9d94c503ab 100644 --- a/soh/soh/Enhancements/boss-rush/BossRush.cpp +++ b/soh/soh/Enhancements/boss-rush/BossRush.cpp @@ -13,7 +13,7 @@ typedef struct BossRushSetting { std::vector> choices; } BossRushSetting; -BossRushSetting BossRushOptions[BOSSRUSH_OPTIONS_AMOUNT] = { +BossRushSetting BossRushOptions[BOSSRUSH_OPTIONS_AMOUNT] = { { { "BOSSES:", "BOSSE:", "BOSS:" }, { @@ -309,7 +309,7 @@ void BossRush_InitSave() { // Set health uint16_t health = 16; - switch (gSaveContext.bossRushOptions[BR_OPTIONS_HEARTS]) { + switch (gSaveContext.bossRushOptions[BR_OPTIONS_HEARTS]) { case BR_CHOICE_HEARTS_7: health *= 7; break; @@ -351,44 +351,39 @@ void BossRush_InitSave() { } // Set items - std::array brItems = { - ITEM_NONE, ITEM_BOMB, ITEM_NONE, ITEM_NUT, ITEM_LENS, ITEM_NONE, - ITEM_NONE, ITEM_SLINGSHOT, ITEM_BOOMERANG, ITEM_STICK, ITEM_NONE, ITEM_NONE, - ITEM_NONE, ITEM_BOW, ITEM_HOOKSHOT, ITEM_HAMMER, ITEM_NONE, ITEM_NONE, - ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, - ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_ARROW_LIGHT, + std::array brItems = { + ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, + ITEM_SLINGSHOT, ITEM_NONE, ITEM_NONE, ITEM_HOOKSHOT, ITEM_NONE, ITEM_NONE, + ITEM_BOOMERANG, ITEM_LENS, ITEM_NONE, ITEM_HAMMER, ITEM_ARROW_LIGHT, ITEM_NONE, + ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, }; if (gSaveContext.bossRushOptions[BR_OPTIONS_LONGSHOT] == BR_CHOICE_LONGSHOT_YES) { - brItems[SLOT_HOOKSHOT] = ITEM_LONGSHOT; + brItems[9] = ITEM_LONGSHOT; } switch (gSaveContext.bossRushOptions[BR_OPTIONS_BOTTLE]) { case BR_CHOICE_BOTTLE_EMPTY: - brItems[SLOT_BOTTLE_1] = ITEM_BOTTLE; + brItems[18] = ITEM_BOTTLE; break; case BR_CHOICE_BOTTLE_FAIRY: - brItems[SLOT_BOTTLE_1] = ITEM_FAIRY; + brItems[18] = ITEM_FAIRY; break; case BR_CHOICE_BOTTLE_REDPOTION: - brItems[SLOT_BOTTLE_1] = ITEM_POTION_RED; + brItems[18] = ITEM_POTION_RED; break; case BR_CHOICE_BOTTLE_GREENPOTION: - brItems[SLOT_BOTTLE_1] = ITEM_POTION_GREEN; + brItems[18] = ITEM_POTION_GREEN; break; case BR_CHOICE_BOTTLE_BLUEPOTION: - brItems[SLOT_BOTTLE_1] = ITEM_POTION_BLUE; + brItems[18] = ITEM_POTION_BLUE; break; default: break; } if (gSaveContext.bossRushOptions[BR_OPTIONS_BUNNYHOOD] == BR_CHOICE_BUNNYHOOD_YES) { - brItems[SLOT_TRADE_CHILD] = ITEM_MASK_BUNNY; - } - - if (gSaveContext.bossRushOptions[BR_OPTIONS_HOVERBOOTS] == BR_CHOICE_HOVERBOOTS_YES) { - brItems[SLOT_BOOTS_HOVER] = ITEM_BOOTS_HOVER; + brItems[23] = ITEM_MASK_BUNNY; } for (int item = 0; item < ARRAY_COUNT(gSaveContext.inventory.items); item++) { @@ -396,12 +391,12 @@ void BossRush_InitSave() { } // Set consumable counts - std::array brAmmo = { 0, 10, 0, 5, 0, 0, 0, 10, 0, 5, 0, 0, 0, 10, 0, 0 }; + std::array brAmmo = { 5, 5, 10, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; if (gSaveContext.bossRushOptions[BR_OPTIONS_AMMO] == BR_CHOICE_AMMO_FULL) { - brAmmo = { 0, 20, 0, 20, 0, 0, 0, 30, 0, 10, 0, 0, 0, 30, 0, 0 }; + brAmmo = { 10, 20, 20, 30, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; } else if (gSaveContext.bossRushOptions[BR_OPTIONS_AMMO] == BR_CHOICE_AMMO_MAXED) { - brAmmo = { 0, 40, 0, 40, 0, 0, 0, 50, 0, 30, 0, 0, 0, 50, 0, 0 }; + brAmmo = { 30, 40, 40, 50, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; } for (int ammo = 0; ammo < ARRAY_COUNT(gSaveContext.inventory.ammo); ammo++) { diff --git a/soh/soh/Enhancements/controls/GameControlEditor.cpp b/soh/soh/Enhancements/controls/GameControlEditor.cpp index e03f40eaebe..d887ba63df7 100644 --- a/soh/soh/Enhancements/controls/GameControlEditor.cpp +++ b/soh/soh/Enhancements/controls/GameControlEditor.cpp @@ -299,7 +299,8 @@ namespace GameControlEditor { UIWidgets::PaddedEnhancementCheckbox("D-pad as Equip Items", "gDpadEquips"); DrawHelpIcon("Equip items and equipment on the D-pad\nIf used with D-pad on Pause Screen, you must hold C-Up to equip instead of navigate"); UIWidgets::PaddedEnhancementCheckbox("Toggle minimap with D-pad down", "gMapOnDDown"); - DrawHelpIcon("Toggle the minimap by pressing down on the D-pad\nIf \"D-pad as Equip Items\" is enabled, equipping an item on D-pad down will prevent you from toggling the map"); + DrawHelpIcon("Toggle the minimap by pressing down on the D-pad\nIf \"D-pad as Equip Items\" is enabled, equipping an item on D-pad down will prevent " + "you from toggling the map, but you can clear the item on D-pad down by re-equipping it over itself."); window->EndGroupPanelPublic(0); } diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index a8a3d54acdb..f38a98a715b 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1328,7 +1328,7 @@ void Draw_Placements(){ ImGui::EndTable(); } } - if (ImGui::CollapsingHeader("DPad items position")) { + if ((CVarGetInteger("gDpadEquips",0) || CVarGetInteger("gAltItemMenu", 0)) && ImGui::CollapsingHeader("DPad items position")) { if (ImGui::BeginTable("tabledpaditems", 1, FlagsTable)) { ImGui::TableSetupColumn("DPad items settings", FlagsCell, TablesCellsWidth); Table_InitHeader(false); diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 66c8944c0f1..19ca9f96980 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -639,16 +639,12 @@ void DrawInventoryTab() { ImGui::Checkbox("Restrict to valid items", &restrictToValid); UIWidgets::InsertHelpHoverText("Restricts items and ammo to only what is possible to legally acquire in-game"); - for (int32_t y = 0; y < 5; y++) { + for (int32_t y = 0; y < 4; y++) { for (int32_t x = 0; x < 6; x++) { int32_t index = x + y * 6; static int32_t selectedIndex = -1; static const char* itemPopupPicker = "itemPopupPicker"; - if (index >= ARRAY_COUNT(gSaveContext.inventory.items)) { - break; - } - ImGui::PushID(index); if (x != 0) { @@ -1709,9 +1705,11 @@ void DrawPlayerTab() { ImGui::SameLine(); ImGui::InputScalar("C Right", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[3], &one, NULL); - ImGui::NewLine(); - ImGui::Text("Current D-pad Equips"); - ImGui::InputScalar("D-pad Up ", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[4], &one, NULL); // Two spaces at the end for aligning, not elegant but it's working + if (CVarGetInteger("gDpadEquips", 0) || CVarGetInteger("gAltItemMenu", 0)) { + ImGui::NewLine(); + ImGui::Text("Current D-pad Equips"); + ImGui::InputScalar("D-pad Up ", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[4], &one, NULL); // Two spaces at the end for aligning, not elegant but it's working + } if (CVarGetInteger("gDpadEquips", 0)) { ImGui::SameLine(); ImGui::InputScalar("D-pad Down", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[5], &one, NULL); diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 6692dd5c971..9a3108676d1 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -1067,6 +1067,71 @@ void RegisterRandomizedEnemySizes() { }); } +void AltItemMenu_Update() { + if (CVarGetInteger("gAltItemMenu", 0)) { // Enabled: force equip ocarina on D-up and match equipped bow, if any + uint16_t targetCBtn = 3; + uint16_t targetButtonIndex = targetCBtn + 1; + for (uint16_t otherSlotIndex = 0; otherSlotIndex < ARRAY_COUNT(gSaveContext.equips.cButtonSlots); otherSlotIndex++) { + uint16_t otherButtonIndex = otherSlotIndex + 1; + if (otherSlotIndex == targetCBtn) { + continue; + } + + if (gSaveContext.equips.cButtonSlots[otherSlotIndex] == SLOT_OCARINA) { + // Assign the other button to the target's current item + if (gSaveContext.equips.buttonItems[targetButtonIndex] != ITEM_NONE) { + gSaveContext.equips.buttonItems[otherButtonIndex] = + gSaveContext.equips.buttonItems[targetButtonIndex]; + gSaveContext.equips.cButtonSlots[otherSlotIndex] = + gSaveContext.equips.cButtonSlots[targetCBtn]; + Interface_LoadItemIcon2(gPlayState, otherButtonIndex); + } else { + gSaveContext.equips.buttonItems[otherButtonIndex] = ITEM_NONE; + gSaveContext.equips.cButtonSlots[otherSlotIndex] = SLOT_NONE; + } + //break; // 'Assume there is only one possible pre-existing equip' + } + + if (gSaveContext.equips.cButtonSlots[otherSlotIndex] == SLOT_BOW) { + switch (gSaveContext.equips.buttonItems[otherButtonIndex]) { + case ITEM_BOW_ARROW_FIRE: + case ITEM_BOW_ARROW_ICE: + case ITEM_BOW_ARROW_LIGHT: + INV_CONTENT(ITEM_BOW) = gSaveContext.equips.buttonItems[otherButtonIndex]; + break; + } + } + } + + gSaveContext.equips.buttonItems[targetButtonIndex] = INV_CONTENT(ITEM_OCARINA_FAIRY); + gSaveContext.equips.cButtonSlots[targetCBtn] = SLOT_OCARINA; + Interface_LoadItemIcon1(gPlayState, targetButtonIndex); + } else { // Disabled: reset bow item to Fairy Bow if some magic arrow is equipped + switch (INV_CONTENT(ITEM_BOW)) { + case ITEM_BOW_ARROW_FIRE: + case ITEM_BOW_ARROW_ICE: + case ITEM_BOW_ARROW_LIGHT: + INV_CONTENT(ITEM_BOW) = ITEM_BOW; + break; + } + } +} + +void AltItemMenu_Register() { + static int altItemMenuOld = -1; + GameInteractor::Instance->RegisterGameHook([]() { + int altItemMenu = CVarGetInteger("gAltItemMenu", 0); + if (altItemMenu != altItemMenuOld) { + AltItemMenu_Update(); + } + altItemMenuOld = altItemMenu; + }); + + GameInteractor::Instance->RegisterGameHook([](int16_t _) { + AltItemMenu_Update(); + }); +} + void InitMods() { RegisterTTS(); RegisterInfiniteMoney(); @@ -1096,4 +1161,5 @@ void InitMods() { RegisterRandomizerSheikSpawn(); RegisterRandomizedEnemySizes(); NameTag_RegisterHooks(); + AltItemMenu_Register(); } diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index cae62e111a7..aece3e4258d 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -175,6 +175,7 @@ const std::vector enhancementsCvars = { "gDisableCritWiggle", "gChestSizeDependsStoneOfAgony", "gSkipArrowAnimation", + "gSeparateArrows", "gCustomizeShootingGallery", "gInstantShootingGalleryWin", "gConstantAdultGallery", @@ -247,6 +248,7 @@ const std::vector enhancementsCvars = { "gAddTraps.Speed", "gAddTraps.Tele", "gAddTraps.Void", + "gAltItemMenu", "gBombArrows", }; @@ -632,6 +634,9 @@ const std::vector enhancedPresetEntries = { // Skip Magic Arrow Equip Animation PRESET_ENTRY_S32("gSkipArrowAnimation", 1), + // Equip arrows on multiple slots + PRESET_ENTRY_S32("gSeparateArrows", 1), + // Disable Navi Call Audio PRESET_ENTRY_S32("gDisableNaviCallAudio", 1), @@ -753,6 +758,9 @@ const std::vector randomizerPresetEntries = { // Exit Market at Night PRESET_ENTRY_S32("gMarketSneak", 1), + // Equip arrows on multiple slots + PRESET_ENTRY_S32("gSeparateArrows", 1), + // Disable Navi Call Audio PRESET_ENTRY_S32("gDisableNaviCallAudio", 1), diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 7ceee4215f3..f918416ece1 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -246,9 +246,9 @@ const char* constCameraStrings[] = { OTRGlobals::OTRGlobals() { std::vector OTRFiles; std::string mqPath = LUS::Context::LocateFileAcrossAppDirs("oot-mq.otr", appShortName); - if (std::filesystem::exists(mqPath)) { + if (std::filesystem::exists(mqPath)) { OTRFiles.push_back(mqPath); - } + } std::string ootPath = LUS::Context::LocateFileAcrossAppDirs("oot.otr", appShortName); if (std::filesystem::exists(ootPath)) { OTRFiles.push_back(ootPath); @@ -278,7 +278,7 @@ OTRGlobals::OTRGlobals() { ); }); OTRFiles.insert(OTRFiles.end(), patchOTRs.begin(), patchOTRs.end()); - std::unordered_set ValidHashes = { + std::unordered_set ValidHashes = { OOT_PAL_MQ, OOT_NTSC_JP_MQ, OOT_NTSC_US_MQ, @@ -865,7 +865,7 @@ void CheckSoHOTRVersion(std::string otrPath) { } // Checks the program version stored in the otr and compares the major value to soh -// For Windows/Mac/Linux if the version doesn't match, offer to +// For Windows/Mac/Linux if the version doesn't match, offer to void DetectOTRVersion(std::string fileName, bool isMQ) { bool isOtrOld = false; std::string otrPath = LUS::Context::LocateFileAcrossAppDirs(fileName, appShortName); @@ -1049,7 +1049,7 @@ extern "C" void InitOTR() { SpeechSynthesizer::Instance = new SAPISpeechSynthesizer(); SpeechSynthesizer::Instance->Init(); #endif - + clearMtx = (uintptr_t)&gMtxClear; OTRMessage_Init(); OTRAudio_Init(); @@ -1084,7 +1084,7 @@ extern "C" void InitOTR() { } #endif - std::shared_ptr conf = OTRGlobals::Instance->context->GetConfig(); + std::shared_ptr conf = OTRGlobals::Instance->context->GetConfig(); conf->RegisterConfigVersionUpdater(std::make_shared()); conf->RegisterConfigVersionUpdater(std::make_shared()); conf->RunVersionUpdates(); @@ -1520,11 +1520,11 @@ std::shared_ptr GetResourceByNameHandlingMQ(const char* path) { extern "C" char* GetResourceDataByNameHandlingMQ(const char* path) { auto res = GetResourceByNameHandlingMQ(path); - + if (res == nullptr) { return nullptr; } - + return (char*)res->GetRawPointer(); } @@ -1611,7 +1611,7 @@ extern "C" char* ResourceMgr_LoadIfDListByName(const char* filePath) { if (res->GetInitData()->Type == LUS::ResourceType::DisplayList) return (char*)&((std::static_pointer_cast(res))->Instructions[0]); - + return nullptr; } @@ -2185,10 +2185,10 @@ extern "C" void AudioPlayer_Play(const uint8_t* buf, uint32_t len) { extern "C" int Controller_ShouldRumble(size_t slot) { auto controlDeck = LUS::Context::GetInstance()->GetControlDeck(); - + if (slot < controlDeck->GetNumConnectedPorts()) { auto physicalDevice = controlDeck->GetDeviceFromPortIndex(slot); - + if (physicalDevice->GetProfile(slot)->UseRumble && physicalDevice->CanRumble()) { return 1; } @@ -2410,7 +2410,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { Player_GetMask(play) == PLAYER_MASK_TRUTH) || (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_STONE && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) { - Actor* stone = GET_PLAYER(play)->targetActor; + Actor* stone = GET_PLAYER(play)->targetActor; actorParams = stone->params; // if we're in a generic grotto @@ -2446,7 +2446,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_GANONDORF); } } else if (textId == TEXT_SHEIK_NEED_HOOK || textId == TEXT_SHEIK_HAVE_HOOK) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId); + messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId); // textId: TEXT_SCRUB_RANDOM + (randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT) } else if (textId >= TEXT_SCRUB_RANDOM && textId <= TEXT_SCRUB_RANDOM + NUM_SCRUBS) { RandomizerInf randoInf = (RandomizerInf)((textId - TEXT_SCRUB_RANDOM) + RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT); @@ -2552,7 +2552,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger("gMarketSneak", 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_MARKET_GUARD_NIGHT); } - if (textId >= TEXT_FIRE_ARROW && textId <= TEXT_LIGHT_ARROW) { + if (textId >= TEXT_FIRE_ARROW && textId <= TEXT_LIGHT_ARROW && CVarGetInteger("gAltItemMenu", 0)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId); } font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition(); @@ -2610,7 +2610,7 @@ void SoH_ProcessDroppedFiles(std::string filePath) { nlohmann::json configJson; configStream >> configJson; - // #region SOH [Randomizer] TODO: Refactor spoiler file handling for randomizer + // #region SOH [Randomizer] TODO: Refactor spoiler file handling for randomizer if (configJson.contains("version") && configJson.contains("finalSeed")) { CVarSetString("gRandomizerDroppedFile", filePath.c_str()); CVarSetInteger("gRandomizerNewFileDropped", 1); diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 293c1b1dd21..e61cf922354 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -662,8 +662,6 @@ void SaveManager::InitFileDebug() { for (int button = 0; button < ARRAY_COUNT(gSaveContext.childEquips.cButtonSlots); button++) { gSaveContext.childEquips.cButtonSlots[button] = SLOT_NONE; } - gSaveContext.childEquips.buttonItems[4] = ITEM_OCARINA_FAIRY; - gSaveContext.childEquips.cButtonSlots[3] = SLOT_OCARINA; gSaveContext.childEquips.equipment = 0; for (int button = 0; button < ARRAY_COUNT(gSaveContext.adultEquips.buttonItems); button++) { gSaveContext.adultEquips.buttonItems[button] = ITEM_NONE; @@ -671,8 +669,6 @@ void SaveManager::InitFileDebug() { for (int button = 0; button < ARRAY_COUNT(gSaveContext.adultEquips.cButtonSlots); button++) { gSaveContext.adultEquips.cButtonSlots[button] = SLOT_NONE; } - gSaveContext.adultEquips.buttonItems[4] = ITEM_OCARINA_FAIRY; - gSaveContext.adultEquips.cButtonSlots[3] = SLOT_OCARINA; gSaveContext.adultEquips.equipment = 0; gSaveContext.unk_54 = 0; gSaveContext.savedSceneNum = 0x51; @@ -686,22 +682,19 @@ void SaveManager::InitFileDebug() { for (int button = 0; button < ARRAY_COUNT(gSaveContext.equips.cButtonSlots); button++) { gSaveContext.equips.cButtonSlots[button] = sCButtonSlots[button]; } - gSaveContext.equips.buttonItems[4] = ITEM_OCARINA_FAIRY; - gSaveContext.equips.cButtonSlots[3] = SLOT_OCARINA; gSaveContext.equips.equipment = 0x1122; // Inventory - static std::array sItems = { - ITEM_DINS_FIRE, ITEM_BOMB, ITEM_BOMBCHU, ITEM_NUT, ITEM_LENS, ITEM_BEAN, - ITEM_FARORES_WIND, ITEM_SLINGSHOT, ITEM_BOOMERANG, ITEM_STICK, ITEM_BOOTS_HOVER, ITEM_WEIRD_EGG, - ITEM_NAYRUS_LOVE, ITEM_BOW, ITEM_HOOKSHOT, ITEM_HAMMER, ITEM_BOOTS_IRON, ITEM_CLAIM_CHECK, - ITEM_NONE, ITEM_BOTTLE, ITEM_POTION_RED, ITEM_POTION_GREEN, ITEM_POTION_BLUE, ITEM_NONE, - ITEM_OCARINA_FAIRY, ITEM_ARROW_FIRE, ITEM_ARROW_ICE, ITEM_ARROW_LIGHT + static std::array sItems = { + ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_ARROW_FIRE, ITEM_DINS_FIRE, + ITEM_SLINGSHOT, ITEM_OCARINA_FAIRY, ITEM_BOMBCHU, ITEM_HOOKSHOT, ITEM_ARROW_ICE, ITEM_FARORES_WIND, + ITEM_BOOMERANG, ITEM_LENS, ITEM_BEAN, ITEM_HAMMER, ITEM_ARROW_LIGHT, ITEM_NAYRUS_LOVE, + ITEM_BOTTLE, ITEM_POTION_RED, ITEM_POTION_GREEN, ITEM_POTION_BLUE, ITEM_POCKET_EGG, ITEM_WEIRD_EGG, }; for (int item = 0; item < ARRAY_COUNT(gSaveContext.inventory.items); item++) { gSaveContext.inventory.items[item] = sItems[item]; } - static std::array sAmmo = { 1, 20, 50, 20, 1, 10, 1, 30, 1, 10, 1, 1, 1, 30, 1, 1 }; + static std::array sAmmo = { 50, 50, 10, 30, 1, 1, 30, 1, 50, 1, 1, 1, 1, 1, 1, 1 }; for (int ammo = 0; ammo < ARRAY_COUNT(gSaveContext.inventory.ammo); ammo++) { gSaveContext.inventory.ammo[ammo] = sAmmo[ammo]; } @@ -795,17 +788,16 @@ void SaveManager::InitFileMaxed() { gSaveContext.equips.equipment = 0x1122; // Inventory - static std::array sItems = { - ITEM_DINS_FIRE, ITEM_BOMB, ITEM_BOMBCHU, ITEM_NUT, ITEM_LENS, ITEM_BEAN, - ITEM_FARORES_WIND, ITEM_SLINGSHOT, ITEM_BOOMERANG, ITEM_STICK, ITEM_BOOTS_HOVER, ITEM_MASK_BUNNY, - ITEM_NAYRUS_LOVE, ITEM_BOW, ITEM_HOOKSHOT, ITEM_HAMMER, ITEM_BOOTS_IRON, ITEM_CLAIM_CHECK, - ITEM_NONE, ITEM_FAIRY, ITEM_FAIRY, ITEM_BUG, ITEM_FISH, ITEM_NONE, - ITEM_OCARINA_TIME, ITEM_ARROW_FIRE, ITEM_ARROW_ICE, ITEM_ARROW_LIGHT, + static std::array sItems = { + ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_ARROW_FIRE, ITEM_DINS_FIRE, + ITEM_SLINGSHOT, ITEM_OCARINA_TIME, ITEM_BOMBCHU, ITEM_LONGSHOT, ITEM_ARROW_ICE, ITEM_FARORES_WIND, + ITEM_BOOMERANG, ITEM_LENS, ITEM_BEAN, ITEM_HAMMER, ITEM_ARROW_LIGHT, ITEM_NAYRUS_LOVE, + ITEM_FAIRY, ITEM_FAIRY, ITEM_BUG, ITEM_FISH, ITEM_CLAIM_CHECK, ITEM_MASK_BUNNY, }; for (int item = 0; item < ARRAY_COUNT(gSaveContext.inventory.items); item++) { gSaveContext.inventory.items[item] = sItems[item]; } - static std::array sAmmo = { 0, 40, 50, 40, 0, 10, 0, 50, 0, 30, 0, 0, 0, 50, 0, 0 }; + static std::array sAmmo = { 30, 40, 40, 50, 0, 0, 50, 0, 50, 0, 0, 0, 0, 0, 15, 0 }; for (int ammo = 0; ammo < ARRAY_COUNT(gSaveContext.inventory.ammo); ammo++) { gSaveContext.inventory.ammo[ammo] = sAmmo[ammo]; } @@ -975,13 +967,13 @@ void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext, int se if (std::filesystem::exists(fileName)) { std::filesystem::remove(fileName); } - + #if defined(__SWITCH__) || defined(__WIIU__) copy_file(tempFile.c_str(), fileName.c_str()); #else std::filesystem::copy_file(tempFile, fileName); #endif - + if (std::filesystem::exists(tempFile)) { std::filesystem::remove(tempFile); } diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 17a0ac4c694..b70428bbee9 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -391,7 +391,7 @@ void DrawSettingsMenu() { UIWidgets::Tooltip("Changes the scaling of the ImGui menu elements."); UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f); - + static std::unordered_map windowBackendNames = { { LUS::WindowBackend::DX11, "DirectX" }, { LUS::WindowBackend::SDL_OPENGL, "OpenGL"}, @@ -468,9 +468,9 @@ void DrawSettingsMenu() { } ImGui::EndMenu(); } - + UIWidgets::Spacer(0); - + if (ImGui::BeginMenu("Accessibility")) { #if defined(_WIN32) || defined(__APPLE__) UIWidgets::PaddedEnhancementCheckbox("Text to Speech", "gA11yTTS"); @@ -478,7 +478,7 @@ void DrawSettingsMenu() { #endif UIWidgets::PaddedEnhancementCheckbox("Disable Idle Camera Re-Centering", "gA11yDisableIdleCam"); UIWidgets::Tooltip("Disables the automatic re-centering of the camera when idle."); - + ImGui::EndMenu(); } ImGui::EndMenu(); @@ -610,6 +610,10 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("Makes nuts explode bombs, similar to how they interact with bombchus. This does not affect bombflowers."); UIWidgets::PaddedEnhancementCheckbox("Bomb Arrows", "gBombArrows", true, false); UIWidgets::Tooltip("Equip bombs onto the same button as your bow to shoot arrows that explode on impact"); + bool disableSeparateArrows = CVarGetInteger("gAltItemMenu", 0); + static const char* disableSeparateArrowsText = "This setting is diabled because \"Rearrange Item Menu\" is on."; + UIWidgets::PaddedEnhancementCheckbox("Equip Multiple Arrows at Once", "gSeparateArrows", true, false, disableSeparateArrows, disableSeparateArrowsText); + UIWidgets::Tooltip("Allow the bow and magic arrows to be equipped at the same time on different slots. (Note this will disable the behaviour of the 'Equip Dupe' glitch)"); UIWidgets::PaddedEnhancementCheckbox("Switch Arrow Types", "gArrowSwitching", true, false); UIWidgets::Tooltip("Press R with the bow out to switch between normal, fire, ice, and light arrows\n" "Use the \"Customize Game Controls\" window to switch with a different button"); @@ -863,6 +867,10 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("Displays an icon and plays a sound when Stone of Agony should be activated, for those without rumble"); UIWidgets::PaddedEnhancementCheckbox("Assignable Tunics and Boots", "gAssignableTunicsAndBoots", true, false); UIWidgets::Tooltip("Allows equipping the tunic and boots to c-buttons"); + UIWidgets::PaddedEnhancementCheckbox("Rearrange Item Menu", "gAltItemMenu", true, false); + UIWidgets::Tooltip("Change the organization of the item subscreen so that boots behave as regular items without the need for " + "\"Assignable Tunics and Boots\". Magic arrows are now accessed from the bow's slot, and the ocarina is always " + "equipped on D-pad up."); UIWidgets::PaddedEnhancementCheckbox("Equipment Toggle", "gEquipmentCanBeRemoved", true, false); UIWidgets::Tooltip("Allows equipment to be removed by toggling it off on\nthe equipment subscreen."); UIWidgets::PaddedEnhancementCheckbox("Extra Underwater Actions", "gEnhancedIronBoots", true, false); @@ -885,7 +893,7 @@ void DrawEnhancementsMenu() { OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_BLUE_FIRE_ARROWS); static const char* forceEnableBlueFireArrowsText = "This setting is forcefully enabled because a savefile\nwith \"Blue Fire Arrows\" is loaded."; - UIWidgets::PaddedEnhancementCheckbox("Blue Fire Arrows", "gBlueFireArrows", true, false, + UIWidgets::PaddedEnhancementCheckbox("Blue Fire Arrows", "gBlueFireArrows", true, false, forceEnableBlueFireArrows, forceEnableBlueFireArrowsText, UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Allows Ice Arrows to melt red ice.\nMay require a room reload if toggled during gameplay."); @@ -894,7 +902,7 @@ void DrawEnhancementsMenu() { OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SUNLIGHT_ARROWS); static const char* forceEnableSunLightArrowsText = "This setting is forcefully enabled because a savefile\nwith \"Sunlight Arrows\" is loaded."; - UIWidgets::PaddedEnhancementCheckbox("Sunlight Arrows", "gSunlightArrows", true, false, + UIWidgets::PaddedEnhancementCheckbox("Sunlight Arrows", "gSunlightArrows", true, false, forceEnableSunLightArrows, forceEnableSunLightArrowsText, UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Allows Light Arrows to activate sun switches.\nMay require a room reload if toggled during gameplay."); @@ -1081,8 +1089,8 @@ void DrawEnhancementsMenu() { "Fixes an incorrect calculation that acted like water underneath ground was above it."); UIWidgets::PaddedEnhancementCheckbox("Fix Bush Item Drops", "gBushDropFix", true, false); UIWidgets::Tooltip("Fixes the bushes to drop items correctly rather than spawning undefined items."); - UIWidgets::PaddedEnhancementCheckbox("Fix falling from vine edges", "gFixVineFall", true, false); - UIWidgets::Tooltip("Prevents immediately falling off climbable surfaces if climbing on the edges."); + UIWidgets::PaddedEnhancementCheckbox("Fix falling from vine edges", "gFixVineFall", true, false); + UIWidgets::Tooltip("Prevents immediately falling off climbable surfaces if climbing on the edges."); UIWidgets::PaddedEnhancementCheckbox("Fix Link's eyes open while sleeping", "gFixEyesOpenWhileSleeping", true, false); UIWidgets::Tooltip("Fixes Link's eyes being open in the opening cutscene when he is supposed to be sleeping."); UIWidgets::PaddedEnhancementCheckbox("Fix Darunia dancing too fast", "gEnhancements.FixDaruniaDanceSpeed", @@ -1415,12 +1423,12 @@ void DrawCheatsMenu() { if (ImGui::Button("Change Age")) { CVarSetInteger("gSwitchAge", 1); } - UIWidgets::Tooltip("Switches Link's age and reloads the area."); + UIWidgets::Tooltip("Switches Link's age and reloads the area."); if (ImGui::Button("Clear Cutscene Pointer")) { GameInteractor::RawAction::ClearCutscenePointer(); } - UIWidgets::Tooltip("Clears the cutscene pointer to a value safe for wrong warps."); + UIWidgets::Tooltip("Clears the cutscene pointer to a value safe for wrong warps."); ImGui::EndDisabled(); @@ -1600,12 +1608,12 @@ void DrawRandomizerMenu() { OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_BOSS_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANYWHERE || (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_VANILLA && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_OWN_DUNGEON && - OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_STARTWITH) || + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY) != RO_GANON_BOSS_KEY_STARTWITH) || !IS_RANDO) { disableKeyColors = false; } - static const char* disableKeyColorsText = + static const char* disableKeyColorsText = "This setting is disabled because a savefile is loaded without any key\n" "shuffle settings set to \"Any Dungeon\", \"Overworld\" or \"Anywhere\""; @@ -1661,4 +1669,4 @@ void SohMenuBar::DrawElement() { ImGui::EndMenuBar(); } } -} // namespace SohGui +} // namespace SohGui diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index cfe92df1907..fe4c65cefb8 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -13,14 +13,14 @@ extern "C" MessageTableEntry* sNesMessageEntryTablePtr; extern "C" MessageTableEntry* sGerMessageEntryTablePtr; extern "C" MessageTableEntry* sFraMessageEntryTablePtr; extern "C" MessageTableEntry* sStaffMessageEntryTablePtr; -//extern "C" MessageTableEntry* _message_0xFFFC_nes; +//extern "C" MessageTableEntry* _message_0xFFFC_nes; MessageTableEntry* OTRMessage_LoadTable(const char* filePath, bool isNES) { auto file = std::static_pointer_cast(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(filePath)); if (file == nullptr) return nullptr; - + // Allocate room for an additional message // OTRTODO: Should not be malloc'ing here. It's fine for now since we check elsewhere that the message table is // already null. diff --git a/soh/src/code/code_80097A00.c b/soh/src/code/code_80097A00.c index 884ad0f13bb..49eab232998 100644 --- a/soh/src/code/code_80097A00.c +++ b/soh/src/code/code_80097A00.c @@ -181,9 +181,7 @@ u8 gItemSlots[] = { SLOT_TRADE_CHILD, SLOT_TRADE_CHILD, SLOT_TRADE_CHILD, SLOT_TRADE_CHILD, SLOT_TRADE_CHILD, SLOT_TRADE_CHILD, SLOT_TRADE_CHILD, SLOT_TRADE_CHILD, SLOT_TRADE_CHILD, SLOT_TRADE_ADULT, SLOT_TRADE_ADULT, SLOT_TRADE_ADULT, SLOT_TRADE_ADULT, SLOT_TRADE_ADULT, SLOT_TRADE_ADULT, SLOT_TRADE_ADULT, SLOT_TRADE_ADULT, SLOT_TRADE_ADULT, - SLOT_TRADE_ADULT, SLOT_TRADE_ADULT, SLOT_BOW, SLOT_BOW, SLOT_BOW, SLOT_NONE, - SLOT_NONE, SLOT_NONE, SLOT_NONE, SLOT_NONE, SLOT_NONE, SLOT_NONE, - SLOT_NONE, SLOT_NONE, SLOT_NONE, SLOT_BOOTS_IRON, SLOT_BOOTS_HOVER, + SLOT_TRADE_ADULT, SLOT_TRADE_ADULT, }; void Inventory_ChangeEquipment(s16 equipment, u16 value) { diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 87c43f98af0..de5b91d8a85 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -1373,7 +1373,7 @@ void EnItem00_DrawCollectible(EnItem00* this, PlayState* play) { Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE); this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING; } - + f32 mtxScale = 10.67f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); EnItem00_CustomItemsParticles(&this->actor, play, this->randoGiEntry); @@ -1534,7 +1534,7 @@ s16 func_8001F404(s16 dropId) { } } - if ((CVarGetInteger("gBombchuDrops", 0) || + if ((CVarGetInteger("gBombchuDrops", 0) || (IS_RANDO && Randomizer_GetSettingValue(RSK_ENABLE_BOMBCHU_DROPS) == 1)) && (dropId == ITEM00_BOMBS_A || dropId == ITEM00_BOMBS_B || dropId == ITEM00_BOMBS_SPECIAL)) { dropId = EnItem00_ConvertBombDropToBombchu(dropId); @@ -1614,7 +1614,7 @@ EnItem00* Item_DropCollectible2(PlayState* play, Vec3f* spawnPos, s16 params) { params &= 0x3FFF; if ((params & 0x00FF) == ITEM00_HEART && CVarGetInteger("gNoHeartDrops", 0)) { return NULL; } - + if (((params & 0x00FF) == ITEM00_FLEXIBLE) && !param4000) { // TODO: Prevent the cast to EnItem00 here since this is a different actor (En_Elf) spawnedActor = (EnItem00*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, spawnPos->x, diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 6099276084a..67730443911 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1451,7 +1451,7 @@ void Inventory_SwapAgeEquipment(void) { u16 shieldEquipValue; if (LINK_AGE_IN_YEARS == YEARS_CHILD) { - + for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if (i != 0) { @@ -1482,7 +1482,6 @@ void Inventory_SwapAgeEquipment(void) { Flags_SetInfTable(INFTABLE_SWORDLESS); } - // Nuts on C-left (if present) if (gSaveContext.inventory.items[SLOT_NUT] != ITEM_NONE) { gSaveContext.equips.buttonItems[1] = ITEM_NUT; gSaveContext.equips.cButtonSlots[0] = SLOT_NUT; @@ -1490,32 +1489,27 @@ void Inventory_SwapAgeEquipment(void) { gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] = ITEM_NONE; } - // Bombs on C-down gSaveContext.equips.buttonItems[2] = ITEM_BOMB; + gSaveContext.equips.buttonItems[3] = gSaveContext.inventory.items[SLOT_OCARINA]; gSaveContext.equips.cButtonSlots[1] = SLOT_BOMB; - - // Nothing on C-right - gSaveContext.equips.buttonItems[3] = ITEM_NONE; - gSaveContext.equips.cButtonSlots[2] = ITEM_NONE; - + gSaveContext.equips.cButtonSlots[2] = SLOT_OCARINA; + gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_MASTER << (EQUIP_TYPE_SWORD * 4)) | (EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) | (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) | (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && + if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && gSaveContext.equips.buttonItems[0] == ITEM_NONE) { gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); } - // Ocarina on D-up - gSaveContext.equips.buttonItems[4] = gSaveContext.inventory.items[SLOT_OCARINA]; - gSaveContext.equips.cButtonSlots[3] = SLOT_OCARINA; - - // Set the rest of the d-pad to nothing + // Set the dpad to nothing + gSaveContext.equips.buttonItems[4] = ITEM_NONE; gSaveContext.equips.buttonItems[5] = ITEM_NONE; gSaveContext.equips.buttonItems[6] = ITEM_NONE; gSaveContext.equips.buttonItems[7] = ITEM_NONE; + gSaveContext.equips.cButtonSlots[3] = SLOT_NONE; gSaveContext.equips.cButtonSlots[4] = SLOT_NONE; gSaveContext.equips.cButtonSlots[5] = SLOT_NONE; gSaveContext.equips.cButtonSlots[6] = SLOT_NONE; @@ -1844,14 +1838,14 @@ u8 Return_Item(u8 itemID, ModIndex modId, ItemID returnItem) { /** * @brief Adds the given item to Link's inventory. - * + * * NOTE: This function has been edited to be safe to use with a NULL play. * If you need to add to this function, be sure you check if the play is not * NULL before doing any operations requiring it. - * - * @param play - * @param item - * @return u8 + * + * @param play + * @param item + * @return u8 */ u8 Item_Give(PlayState* play, u8 item) { lusprintf(__FILE__, __LINE__, 2, "Item Give - item: %#x", item); @@ -1932,10 +1926,10 @@ u8 Item_Give(PlayState* play, u8 item) { // In rando, when buying Giant's Knife, also check // without the Koriri Sword in case we don't have it - if (ALL_EQUIP_VALUE(EQUIP_TYPE_SWORD) == + if (ALL_EQUIP_VALUE(EQUIP_TYPE_SWORD) == ((1 << EQUIP_INV_SWORD_KOKIRI) | (1 << EQUIP_INV_SWORD_MASTER) | (1 << EQUIP_INV_SWORD_BIGGORON) | - (1 << EQUIP_INV_SWORD_BROKENGIANTKNIFE)) || - (IS_RANDO && ALL_EQUIP_VALUE(EQUIP_TYPE_SWORD) == + (1 << EQUIP_INV_SWORD_BROKENGIANTKNIFE)) || + (IS_RANDO && ALL_EQUIP_VALUE(EQUIP_TYPE_SWORD) == ((1 << EQUIP_INV_SWORD_MASTER) | (1 << EQUIP_INV_SWORD_BIGGORON) | (1 << EQUIP_INV_SWORD_BROKENGIANTKNIFE)))) { gSaveContext.inventory.equipment ^= OWNED_EQUIP_FLAG_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BROKENGIANTKNIFE); @@ -1947,7 +1941,7 @@ u8 Item_Give(PlayState* play, u8 item) { } } } - + } else if (item == ITEM_SWORD_MASTER) { gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); @@ -1966,9 +1960,6 @@ u8 Item_Give(PlayState* play, u8 item) { return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item >= ITEM_BOOTS_KOKIRI) && (item <= ITEM_BOOTS_HOVER)) { gSaveContext.inventory.equipment |= OWNED_EQUIP_FLAG(EQUIP_TYPE_BOOTS, item - ITEM_BOOTS_KOKIRI); - if (item != ITEM_BOOTS_KOKIRI) { - INV_CONTENT(item) = item; - } return Return_Item(item, MOD_NONE, ITEM_NONE); } else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) { gSaveContext.inventory.dungeonItems[gSaveContext.mapIndex] |= gBitFlags[item - ITEM_KEY_BOSS]; @@ -2239,14 +2230,6 @@ u8 Item_Give(PlayState* play, u8 item) { return Return_Item(item, MOD_NONE, ITEM_SEEDS); } else if (item == ITEM_OCARINA_FAIRY) { INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY; - - gSaveContext.equips.buttonItems[4] = item; - gSaveContext.equips.cButtonSlots[3] = SLOT_OCARINA; - gSaveContext.childEquips.buttonItems[4] = item; - gSaveContext.childEquips.cButtonSlots[3] = SLOT_OCARINA; - gSaveContext.adultEquips.buttonItems[4] = item; - gSaveContext.adultEquips.cButtonSlots[3] = SLOT_OCARINA; - return Return_Item(item, MOD_NONE, ITEM_NONE); } else if (item == ITEM_OCARINA_TIME) { INV_CONTENT(ITEM_OCARINA_TIME) = ITEM_OCARINA_TIME; @@ -2698,7 +2681,7 @@ u8 Item_CheckObtainability(u8 item) { return ITEM_NONE; } } - + if ((item >= ITEM_SONG_MINUET) && (item <= ITEM_SONG_STORMS)) { return ITEM_NONE; } else if ((item >= ITEM_MEDALLION_FOREST) && (item <= ITEM_MEDALLION_LIGHT)) { @@ -2962,7 +2945,7 @@ bool Inventory_HatchPocketCucco(PlayState* play) { return Inventory_ReplaceItem(play, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO); } - if (!PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_POCKET_EGG)) { + if (!PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_POCKET_EGG)) { return 0; } @@ -3001,7 +2984,7 @@ void Interface_LoadActionLabel(InterfaceContext* interfaceCtx, u16 action, s16 l } doAction = newName[loadOffset]; } - + char* segment = interfaceCtx->doActionSegment[loadOffset]; interfaceCtx->doActionSegment[loadOffset] = action != DO_ACTION_NONE ? doAction : gEmptyTexture; gSegments[7] = interfaceCtx->doActionSegment[loadOffset]; @@ -3068,7 +3051,7 @@ void Interface_LoadActionLabelB(PlayState* play, u16 action) { } interfaceCtx->unk_1FC = action; - + char* segment = interfaceCtx->doActionSegment[1]; interfaceCtx->doActionSegment[1] = action != DO_ACTION_NONE ? doAction : gEmptyTexture; osRecvMesg(&interfaceCtx->loadQueue, NULL, OS_MESG_BLOCK); @@ -3093,7 +3076,7 @@ s32 Health_ChangeBy(PlayState* play, s16 healthChange) { if (healthChange < 0) { gSaveContext.health = 0; } - + return 0; } @@ -3162,7 +3145,7 @@ void Rupees_ChangeBy(s16 rupeeChange) { void GameplayStats_UpdateAmmoUsed(s16 item, s16 ammoUsed) { - switch (item) { + switch (item) { case ITEM_STICK: gSaveContext.sohStats.count[COUNT_AMMO_USED_STICK] += ammoUsed; break; @@ -3506,7 +3489,7 @@ void Interface_UpdateMagicBar(PlayState* play) { (msgCtx->msgMode == MSGMODE_NONE) && (play->gameOverCtx.state == GAMEOVER_INACTIVE) && (play->sceneLoadFlag == 0) && (play->transitionMode == 0) && !Play_InCsMode(play)) { bool hasLens = false; - for (int buttonIndex = 1; buttonIndex < (CVarGetInteger("gDpadEquips", 0)) ? ARRAY_COUNT(gSaveContext.equips.buttonItems) : 5; buttonIndex++) { + for (int buttonIndex = 1; buttonIndex < (CVarGetInteger("gDpadEquips", 0) != 0) ? ARRAY_COUNT(gSaveContext.equips.buttonItems) : 4; buttonIndex++) { if (gSaveContext.equips.buttonItems[buttonIndex] == ITEM_LENS) { hasLens = true; break; @@ -4348,7 +4331,7 @@ void Interface_DrawItemButtons(PlayState* play) { G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - gSPWideTextureRectangle(OVERLAY_DISP++, C_Up_BTN_Pos[0]-LabelX_Navi << 2, C_Up_BTN_Pos[1]+LabelY_Navi << 2, + gSPWideTextureRectangle(OVERLAY_DISP++, C_Up_BTN_Pos[0]-LabelX_Navi << 2, C_Up_BTN_Pos[1]+LabelY_Navi << 2, (C_Up_BTN_Pos[0]-LabelX_Navi + 32) << 2, (C_Up_BTN_Pos[1]+LabelY_Navi + 8) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); } @@ -4466,7 +4449,7 @@ void Interface_DrawItemButtons(PlayState* play) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, cRightButtonColor.r, cRightButtonColor.g, cRightButtonColor.b, interfaceCtx->cRightAlpha); } - OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, ((u8*)gButtonBackgroundTex), 32, 32, + OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, ((u8*)gButtonBackgroundTex), 32, 32, ItemIconPos[temp-1][0], ItemIconPos[temp-1][1], ItemIconWidthFactor[temp-1][0], ItemIconWidthFactor[temp-1][0], ItemIconWidthFactor[temp-1][1], ItemIconWidthFactor[temp-1][1]); @@ -4541,8 +4524,8 @@ void Interface_DrawItemIconTexture(PlayState* play, void* texture, s16 button) { { C_DOWN_BUTTON_X+X_Margins_CD, C_DOWN_BUTTON_Y+Y_Margins_CD }, { C_RIGHT_BUTTON_X+X_Margins_CR, C_RIGHT_BUTTON_Y+Y_Margins_CR }, { DPAD_UP_X+X_Margins_DPad_Items, DPAD_UP_Y+Y_Margins_DPad_Items }, - { DPAD_DOWN_X+X_Margins_DPad_Items, DPAD_DOWN_Y+Y_Margins_DPad_Items }, - { DPAD_LEFT_X+X_Margins_DPad_Items, DPAD_LEFT_Y+Y_Margins_DPad_Items }, + { DPAD_DOWN_X+X_Margins_DPad_Items, DPAD_DOWN_Y+Y_Margins_DPad_Items }, + { DPAD_LEFT_X+X_Margins_DPad_Items, DPAD_LEFT_Y+Y_Margins_DPad_Items }, { DPAD_RIGHT_X+X_Margins_DPad_Items, DPAD_RIGHT_Y+Y_Margins_DPad_Items } }; u16 ItemsSlotsAlpha[8] = { @@ -4930,11 +4913,11 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { } if (i != 0) { - OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, (u8*)_gAmmoDigit0Tex[i], 8, 8, + OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, (u8*)_gAmmoDigit0Tex[i], 8, 8, ItemIconPos[button][0], ItemIconPos[button][1], 8, 8, 1 << 10, 1 << 10); } - OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, (u8*)_gAmmoDigit0Tex[ammo], 8, 8, + OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, (u8*)_gAmmoDigit0Tex[ammo], 8, 8, ItemIconPos[button][0] + 6, ItemIconPos[button][1], 8, 8, 1 << 10, 1 << 10); } @@ -5454,7 +5437,7 @@ void Interface_Draw(PlayState* play) { PosY_adjust = 6; PosX_adjust = -10; } - + s16 BbtnPosX; s16 BbtnPosY; s16 X_Margins_BtnB_label; @@ -5538,83 +5521,86 @@ void Interface_Draw(PlayState* play) { Interface_DrawAmmoCount(play, 3, interfaceCtx->cRightAlpha); } - // DPad is only greyed-out when all 4 DPad directions are too - uint16_t dpadAlpha = - MAX(MAX(MAX(interfaceCtx->dpadUpAlpha, interfaceCtx->dpadDownAlpha), interfaceCtx->dpadLeftAlpha), - interfaceCtx->dpadRightAlpha); - - // Draw DPad - s16 DpadPosX; - s16 DpadPosY; - s16 X_Margins_Dpad; - s16 Y_Margins_Dpad; - if (CVarGetInteger("gDPadUseMargins", 0) != 0) { - if (CVarGetInteger("gDPadPosType", 0) == 0) {X_Margins_Dpad = Right_HUD_Margin;}; - Y_Margins_Dpad = (Top_HUD_Margin*-1); - } else { - Y_Margins_Dpad = 0; - X_Margins_Dpad = 0; - } - if (CVarGetInteger("gDPadPosType", 0) != 0) { - DpadPosY = CVarGetInteger("gDPadPosY", 0)+Y_Margins_Dpad; - if (CVarGetInteger("gDPadPosType", 0) == 1) {//Anchor Left - if (CVarGetInteger("gDPadUseMargins", 0) != 0) {X_Margins_Dpad = Left_HUD_Margin;}; - DpadPosX = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_Dpad); - } else if (CVarGetInteger("gDPadPosType", 0) == 2) {//Anchor Right - if (CVarGetInteger("gDPadUseMargins", 0) != 0) {X_Margins_Dpad = Right_HUD_Margin;}; - DpadPosX = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_Dpad); - } else if (CVarGetInteger("gDPadPosType", 0) == 3) {//Anchor None - DpadPosX = CVarGetInteger("gDPadPosX", 0); - } else if (CVarGetInteger("gDPadPosType", 0) == 4) {//Hidden - DpadPosX = -9999; + bool altItemMenu = CVarGetInteger("gAltItemMenu", 0); + bool dpadEquips = CVarGetInteger("gDpadEquips", 0); + if (dpadEquips || altItemMenu) { + // DPad is only greyed-out when all 4 DPad directions are too + uint16_t dpadAlpha = + MAX(MAX(MAX(interfaceCtx->dpadUpAlpha, interfaceCtx->dpadDownAlpha), interfaceCtx->dpadLeftAlpha), + interfaceCtx->dpadRightAlpha); + + // Draw DPad + s16 DpadPosX; + s16 DpadPosY; + s16 X_Margins_Dpad; + s16 Y_Margins_Dpad; + if (CVarGetInteger("gDPadUseMargins", 0) != 0) { + if (CVarGetInteger("gDPadPosType", 0) == 0) {X_Margins_Dpad = Right_HUD_Margin;}; + Y_Margins_Dpad = (Top_HUD_Margin*-1); + } else { + Y_Margins_Dpad = 0; + X_Margins_Dpad = 0; + } + if (CVarGetInteger("gDPadPosType", 0) != 0) { + DpadPosY = CVarGetInteger("gDPadPosY", 0)+Y_Margins_Dpad; + if (CVarGetInteger("gDPadPosType", 0) == 1) {//Anchor Left + if (CVarGetInteger("gDPadUseMargins", 0) != 0) {X_Margins_Dpad = Left_HUD_Margin;}; + DpadPosX = OTRGetDimensionFromLeftEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_Dpad); + } else if (CVarGetInteger("gDPadPosType", 0) == 2) {//Anchor Right + if (CVarGetInteger("gDPadUseMargins", 0) != 0) {X_Margins_Dpad = Right_HUD_Margin;}; + DpadPosX = OTRGetDimensionFromRightEdge(CVarGetInteger("gDPadPosX", 0)+X_Margins_Dpad); + } else if (CVarGetInteger("gDPadPosType", 0) == 3) {//Anchor None + DpadPosX = CVarGetInteger("gDPadPosX", 0); + } else if (CVarGetInteger("gDPadPosType", 0) == 4) {//Hidden + DpadPosX = -9999; + } + } else { + DpadPosX = OTRGetRectDimensionFromRightEdge(DPAD_X+X_Margins_Dpad); + DpadPosY = DPAD_Y+Y_Margins_Dpad; } - } else { - DpadPosX = OTRGetRectDimensionFromRightEdge(DPAD_X+X_Margins_Dpad); - DpadPosY = DPAD_Y+Y_Margins_Dpad; - } - gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); + gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, dPadColor.r, dPadColor.g, dPadColor.b, dpadAlpha); - if (fullUi) { - gDPLoadTextureBlock(OVERLAY_DISP++, gDPadTex, - G_IM_FMT_IA, G_IM_SIZ_16b, 32, 32, 0, G_TX_NOMIRROR | G_TX_WRAP, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - gSPWideTextureRectangle(OVERLAY_DISP++, DpadPosX << 2, DpadPosY << 2, - (DpadPosX + 32) << 2, (DpadPosY + 32) << 2, - G_TX_RENDERTILE, 0, 0, (1 << 10), (1 << 10)); + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, dPadColor.r, dPadColor.g, dPadColor.b, dpadAlpha); + if (fullUi) { + gDPLoadTextureBlock(OVERLAY_DISP++, gDPadTex, + G_IM_FMT_IA, G_IM_SIZ_16b, 32, 32, 0, G_TX_NOMIRROR | G_TX_WRAP, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gSPWideTextureRectangle(OVERLAY_DISP++, DpadPosX << 2, DpadPosY << 2, + (DpadPosX + 32) << 2, (DpadPosY + 32) << 2, + G_TX_RENDERTILE, 0, 0, (1 << 10), (1 << 10)); + } } - bool dpadEquips = CVarGetInteger("gDpadEquips", 0); + if (dpadEquips || altItemMenu) { + // DPad-Up Button Icon & Ammo Count + if (gSaveContext.equips.buttonItems[4] < 0xF0) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->dpadUpAlpha); + gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM); + Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[4]], 4); + gDPPipeSync(OVERLAY_DISP++); + gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, + PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0); + Interface_DrawAmmoCount(play, 4, interfaceCtx->dpadUpAlpha); + } - // DPad-Up Button Icon & Ammo Count - // Ocarina is perma-mapped to D-up, so that part has to be drawn - if (gSaveContext.equips.buttonItems[4] < 0xF0) { - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->dpadUpAlpha); - gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM); - Interface_DrawItemIconTexture(play, gItemIcons[gSaveContext.equips.buttonItems[4]], 4); - gDPPipeSync(OVERLAY_DISP++); - gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, - PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0); - Interface_DrawAmmoCount(play, 4, interfaceCtx->dpadUpAlpha); - } - - // DPad-Down Button Icon & Ammo Count - bool itemOnDpad = dpadEquips && gSaveContext.equips.buttonItems[5] < 0xF0; - bool dpadMap = fullUi && CVarGetInteger("gMapOnDDown", 0) && - play->pauseCtx.state < 4 && - ((play->sceneNum >= SCENE_DEKU_TREE && play->sceneNum <= SCENE_ICE_CAVERN) || - (play->sceneNum >= SCENE_HYRULE_FIELD && play->sceneNum <= SCENE_OUTSIDE_GANONS_CASTLE)); - if (itemOnDpad || dpadMap) { - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->dpadDownAlpha); - gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM); - void* texture = gItemIcons[itemOnDpad ? gSaveContext.equips.buttonItems[5] : ITEM_DUNGEON_MAP]; - Interface_DrawItemIconTexture(play, texture, 5); - gDPPipeSync(OVERLAY_DISP++); - gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, - PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0); - if (itemOnDpad) { - Interface_DrawAmmoCount(play, 5, interfaceCtx->dpadDownAlpha); + // DPad-Down Button Icon & Ammo Count + bool itemOnDpad = dpadEquips && gSaveContext.equips.buttonItems[5] < 0xF0; + bool dpadMap = fullUi && CVarGetInteger("gMapOnDDown", 0) && + play->pauseCtx.state < 4 && + ((play->sceneNum >= SCENE_DEKU_TREE && play->sceneNum <= SCENE_ICE_CAVERN) || + (play->sceneNum >= SCENE_HYRULE_FIELD && play->sceneNum <= SCENE_OUTSIDE_GANONS_CASTLE)); + if (itemOnDpad || dpadMap) { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->dpadDownAlpha); + gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATERGBA_PRIM, G_CC_MODULATERGBA_PRIM); + void* texture = gItemIcons[itemOnDpad ? gSaveContext.equips.buttonItems[5] : ITEM_DUNGEON_MAP]; + Interface_DrawItemIconTexture(play, texture, 5); + gDPPipeSync(OVERLAY_DISP++); + gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, + PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0); + if (itemOnDpad) { + Interface_DrawAmmoCount(play, 5, interfaceCtx->dpadDownAlpha); + } } } @@ -5783,7 +5769,7 @@ void Interface_Draw(PlayState* play) { CarrotsPosY = CVarGetInteger("gCarrotsPosY", 0); if (CVarGetInteger("gCarrotsPosType", 0) == 1) {//Anchor Left if (CVarGetInteger("gCarrotsUseMargins", 0) != 0) {CarrotsMargins_X = Left_HUD_Margin;}; - CarrotsPosX = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCarrotsPosX", 0)+CarrotsMargins_X); + CarrotsPosX = OTRGetDimensionFromLeftEdge(CVarGetInteger("gCarrotsPosX", 0)+CarrotsMargins_X); } else if (CVarGetInteger("gCarrotsPosType", 0) == 2) {//Anchor Right if (CVarGetInteger("gCarrotsUseMargins", 0) != 0) {CarrotsMargins_X = Right_HUD_Margin;}; CarrotsPosX = OTRGetDimensionFromRightEdge(CVarGetInteger("gCarrotsPosX", 0)+CarrotsMargins_X); @@ -6293,7 +6279,7 @@ void Interface_Draw(PlayState* play) { for (svar1 = 0; svar1 < 5; svar1++) { // clang-format off //svar5 = svar5 + 8; - //svar5 = OTRGetRectDimensionFromLeftEdge(gSaveContext.timerX[svar6]); + //svar5 = OTRGetRectDimensionFromLeftEdge(gSaveContext.timerX[svar6]); OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP, digitTextures[timerDigits[svar1]], 8, 16, svar5 + timerDigitLeftPos[svar1], svar2, digitWidth[svar1], VREG(42), VREG(43) << 1, @@ -6437,7 +6423,7 @@ void Interface_Update(PlayState* play) { Left_HUD_Margin = CVarGetInteger("gHUDMargin_L", 0); Right_HUD_Margin = CVarGetInteger("gHUDMargin_R", 0); Bottom_HUD_Margin = CVarGetInteger("gHUDMargin_B", 0); - + GameInteractor_ExecuteOnInterfaceUpdate(); if (CHECK_BTN_ALL(debugInput->press.button, BTN_DLEFT)) { diff --git a/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c b/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c index cf011c07064..93ff272f4d9 100644 --- a/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c +++ b/soh/src/overlays/actors/ovl_Arms_Hook/z_arms_hook.c @@ -257,9 +257,9 @@ void ArmsHook_Shoot(ArmsHook* this, PlayState* play) { sp60.x = this->unk_1F4.x - (this->unk_1E8.x - this->unk_1F4.x); sp60.y = this->unk_1F4.y - (this->unk_1E8.y - this->unk_1F4.y); sp60.z = this->unk_1F4.z - (this->unk_1E8.z - this->unk_1F4.z); - u16 buttonsToCheck = BTN_A | BTN_B | BTN_R | BTN_CUP | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN | BTN_DUP; + u16 buttonsToCheck = BTN_A | BTN_B | BTN_R | BTN_CUP | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN; if (CVarGetInteger("gDpadEquips", 0) != 0) { - buttonsToCheck |= BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; + buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } if (BgCheck_EntityLineTest1(&play->colCtx, &sp60, &this->unk_1E8, &sp78, &poly, true, true, true, true, &bgId) && 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 5828bce3de4..204fc34cda4 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2030,7 +2030,15 @@ s32 func_80833C98(s32 item1, s32 actionParam) { } s32 func_80833CDC(PlayState* play, s32 index) { - if (index >= ((CVarGetInteger("gDpadEquips", 0) != 0) ? 8 : 5)) { + int buttons; + if (CVarGetInteger("gDpadEquips", 0)) { + buttons = 8; + } else if (CVarGetInteger("gAltItemMenu", 0)) { + buttons = 5; + } else { + buttons = 4; + } + if (index >= buttons) { return ITEM_NONE; } else if (play->bombchuBowlingStatus != 0) { return (play->bombchuBowlingStatus > 0) ? ITEM_BOMBCHU : ITEM_NONE; @@ -2063,7 +2071,7 @@ void func_80833DF8(Player* this, PlayState* play) { s32 maskItem = this->currentMask - PLAYER_MASK_KEATON + ITEM_MASK_KEATON; bool hasOnDpad = false; if (CVarGetInteger("gDpadEquips", 0) != 0) { - for (int buttonIndex = 5; buttonIndex < 8; buttonIndex++) { + for (int buttonIndex = 4; buttonIndex < 8; buttonIndex++) { hasOnDpad |= gSaveContext.equips.buttonItems[buttonIndex] == maskItem; } } @@ -2078,7 +2086,7 @@ void func_80833DF8(Player* this, PlayState* play) { maskActionParam = this->currentMask - 1 + PLAYER_IA_MASK_KEATON; bool hasOnDpad = false; if (CVarGetInteger("gDpadEquips", 0) != 0) { - for (int buttonIndex = 0; buttonIndex < 5; buttonIndex++) { + for (int buttonIndex = 0; buttonIndex < 4; buttonIndex++) { hasOnDpad |= func_80833C98(DPAD_ITEM(buttonIndex), maskActionParam); } } @@ -2089,8 +2097,8 @@ void func_80833DF8(Player* this, PlayState* play) { } } - // Since boots are items now, take them off if not equipped on a button - if (this->currentBoots != PLAYER_BOOTS_KOKIRI) { + // Alt item menu: Since boots are items, take them off if not equipped on a button + if (CVarGetInteger("gAltItemMenu", 0) && this->currentBoots != PLAYER_BOOTS_KOKIRI) { s32 bootsItemAction = this->currentBoots + PLAYER_IA_BOOTS_KOKIRI; bool hasOnCBtn = false; @@ -2596,9 +2604,12 @@ s32 func_80834E44(PlayState* play) { } s32 func_80834E7C(PlayState* play) { - u16 buttonsToCheck = BTN_A | BTN_B | BTN_CUP | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN | BTN_DUP; + u16 buttonsToCheck = BTN_A | BTN_B | BTN_CUP | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN; + if (CVarGetInteger("gAltItemMenu", 0)) { + buttonsToCheck |= BTN_DUP; + } if (CVarGetInteger("gDpadEquips", 0) != 0) { - buttonsToCheck |= BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; + buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } return (play->shootingGalleryStatus != 0) && ((play->shootingGalleryStatus < 0) || CHECK_BTN_ANY(sControlInput->cur.button, buttonsToCheck)); @@ -5084,7 +5095,7 @@ s32 func_8083AD4C(PlayState* play, Player* this) { if(CVarGetInteger("gBowSlingShotAmmoFix", 0)){ shouldUseBowCamera = this->heldItemAction != PLAYER_IA_SLINGSHOT; } - + cameraMode = shouldUseBowCamera ? CAM_MODE_BOWARROW : CAM_MODE_SLINGSHOT; } else { cameraMode = CAM_MODE_BOOMERANG; @@ -5532,7 +5543,7 @@ s32 func_8083BDBC(Player* this, PlayState* play) { if (sp2C == 2) { gSaveContext.sohStats.count[COUNT_BACKFLIPS]++; } - + return 1; } } @@ -6260,8 +6271,8 @@ void func_8083DFE0(Player* this, f32* arg1, s16* arg2) { if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) == BUNNY_HOOD_FAST_AND_JUMP && this->currentMask == PLAYER_MASK_BUNNY) { maxSpeed *= 1.5f; - } - + } + if (CVarGetInteger("gEnableWalkModify", 0) && !CVarGetInteger("gWalkModifierDoesntChangeJump", 0)) { if (CVarGetInteger("gWalkSpeedToggle", 0)) { if (gWalkSpeedToggle1) { @@ -6504,8 +6515,8 @@ s32 func_8083E5A8(Player* this, PlayState* play) { uint8_t showItemCutscene = play->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY || Item_CheckObtainability(giEntry.itemId) == ITEM_NONE || IS_RANDO; // Only skip cutscenes for drops when they're items/consumables from bushes/rocks/enemies. - uint8_t isDropToSkip = (interactedActor->id == ACTOR_EN_ITEM00 && interactedActor->params != 6 && interactedActor->params != 17) || - interactedActor->id == ACTOR_EN_KAREBABA || + uint8_t isDropToSkip = (interactedActor->id == ACTOR_EN_ITEM00 && interactedActor->params != 6 && interactedActor->params != 17) || + interactedActor->id == ACTOR_EN_KAREBABA || interactedActor->id == ACTOR_EN_DEKUBABA; // Skip cutscenes from picking up consumables with "Fast Pickup Text" enabled, even when the player never picked it up before. @@ -6636,9 +6647,12 @@ s32 func_8083EAF0(Player* this, Actor* actor) { } s32 func_8083EB44(Player* this, PlayState* play) { - u16 buttonsToCheck = BTN_A | BTN_B | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN | BTN_DUP; + u16 buttonsToCheck = BTN_A | BTN_B | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN; + if (CVarGetInteger("gAltItemMenu", 0)) { + buttonsToCheck |= BTN_DUP; + } if (CVarGetInteger("gDpadEquips", 0) != 0) { - buttonsToCheck |= BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; + buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } if ((this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) && (this->heldActor != NULL) && CHECK_BTN_ANY(sControlInput->press.button, buttonsToCheck)) { @@ -7913,7 +7927,7 @@ void func_80842180(Player* this, PlayState* play) { if (CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && this->currentMask == PLAYER_MASK_BUNNY) { sp2C *= 1.5f; } - + if (CVarGetInteger("gEnableWalkModify", 0)) { if (CVarGetInteger("gWalkSpeedToggle", 0)) { if (gWalkSpeedToggle1) { @@ -8700,9 +8714,12 @@ void func_8084411C(Player* this, PlayState* play) { if (this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { Actor* heldActor = this->heldActor; - u16 buttonsToCheck = BTN_A | BTN_B | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN | BTN_DUP; + u16 buttonsToCheck = BTN_A | BTN_B | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN; + if (CVarGetInteger("gAltItemMenu", 0)) { + buttonsToCheck |= BTN_DUP; + } if (CVarGetInteger("gDpadEquips", 0) != 0) { - buttonsToCheck |= BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; + buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } if (!func_80835644(play, this, heldActor) && (heldActor->id == ACTOR_EN_NIW) && CHECK_BTN_ANY(sControlInput->press.button, buttonsToCheck)) { @@ -9482,7 +9499,10 @@ void func_80846260(Player* this, PlayState* play) { return; } - u16 buttonsToCheck = BTN_A | BTN_B | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN | BTN_DUP; + u16 buttonsToCheck = BTN_A | BTN_B | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN; + if (CVarGetInteger("gAltItemMenu", 0)) { + buttonsToCheck |= BTN_DUP; + } if (CVarGetInteger("gDpadEquips", 0) != 0) { buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } @@ -11349,7 +11369,7 @@ void Player_Update(Actor* thisx, PlayState* play) { // Play fan sound (too annoying) //func_8002F974(&player->actor, NA_SE_EV_WIND_TRAP - SFX_FLAG); } - + GameInteractor_ExecuteOnPlayerUpdate(); } @@ -11400,7 +11420,7 @@ void Player_DrawGameplay(PlayState* play, Player* this, s32 lod, Gfx* cullDList, MATRIX_TOMTX(sp70); } - + if (this->currentMask != PLAYER_MASK_BUNNY || !CVarGetInteger("gHideBunnyHood", 0)) { gSPDisplayList(POLY_OPA_DISP++, sMaskDlists[this->currentMask - 1]); } @@ -11752,9 +11772,12 @@ void func_8084B1D8(Player* this, PlayState* play) { func_80836670(this, play); } - u16 itemButtons = BTN_A | BTN_B | BTN_R | BTN_CUP | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN | BTN_DUP; + u16 itemButtons = BTN_A | BTN_B | BTN_R | BTN_CUP | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN; + if (CVarGetInteger("gAltItemMenu", 0)) { + itemButtons |= BTN_DUP; + } if (CVarGetInteger("gDpadEquips", 0) != 0) { - itemButtons |= BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; + itemButtons |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } u16 returnButtons = BTN_A | BTN_B | BTN_R; if (Player_CanSwitchArrows(this)) { @@ -13754,7 +13777,7 @@ void func_8084F88C(Player* this, PlayState* play) { play->nextEntranceIndex = 0x0088; } else if (this->unk_84F < 0) { Play_TriggerRespawn(play); - // In ER, handle DMT and other special void outs to respawn from last entrance from grotto + // In ER, handle DMT and other special void outs to respawn from last entrance from grotto if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) { Grotto_ForceRegularVoidOut(); } @@ -15181,7 +15204,7 @@ void func_80852648(PlayState* play, Player* this, CsCmdActorAction* arg2) { this->heldItemId = ITEM_NONE; this->modelGroup = this->nextModelGroup = Player_ActionToModelGroup(this, PLAYER_IA_NONE); this->leftHandDLists = gPlayerLeftHandOpenDLs; - + // If MS sword is shuffled and not in the players inventory, then we need to unequip the current sword // and set swordless flag to mimic Link having his weapon knocked out of his hand in the Ganon fight if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) { @@ -15190,7 +15213,7 @@ void func_80852648(PlayState* play, Player* this, CsCmdActorAction* arg2) { Flags_SetInfTable(INFTABLE_SWORDLESS); return; } - + Inventory_ChangeEquipment(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_MASTER); gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; Inventory_DeleteEquipment(play, EQUIP_TYPE_SWORD); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index 3a460d94e82..939030f99d3 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -181,6 +181,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { bool dpad = (CVarGetInteger("gDpadPause", 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); bool pauseAnyCursor = (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); + bool altItems = CVarGetInteger("gAltItemMenu", 0); OPEN_DISPS(play->state.gfxCtx); @@ -188,7 +189,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, ZREG(39), ZREG(40), ZREG(41), pauseCtx->alpha); gDPSetEnvColor(POLY_KAL_DISP++, ZREG(43), ZREG(44), ZREG(45), 0); - for (i = 0, j = 64; i < 3; i++, j += 4) { + for (i = 0, j = 64; i < (altItems ? 3 : 4); i++, j += 4) { if (CUR_EQUIP_VALUE(i) != 0) { gDPPipeSync(POLY_KAL_DISP++); gSPVertex(POLY_KAL_DISP++, &pauseCtx->equipVtx[j], 4, 0); @@ -221,7 +222,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { pauseCtx->cursorPoint[PAUSE_EQUIP] -= 1; // Kokiri tunic -> scale - if (pauseCtx->cursorY[PAUSE_EQUIP] == 2 && pauseCtx->cursorX[PAUSE_EQUIP] == 0) { + if (altItems && pauseCtx->cursorY[PAUSE_EQUIP] == 2 && pauseCtx->cursorX[PAUSE_EQUIP] == 0) { pauseCtx->cursorY[PAUSE_EQUIP] += 1; pauseCtx->cursorPoint[PAUSE_EQUIP] += 4; } @@ -268,7 +269,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { // Strength -> Deku shield // Scale -> Kokiri tunic - if (pauseCtx->cursorX[PAUSE_EQUIP] == 1 && pauseCtx->cursorY[PAUSE_EQUIP] >= 2) { + if (altItems && pauseCtx->cursorX[PAUSE_EQUIP] == 1 && pauseCtx->cursorY[PAUSE_EQUIP] >= 2) { pauseCtx->cursorY[PAUSE_EQUIP] -= 1; pauseCtx->cursorPoint[PAUSE_EQUIP] -= 4; } @@ -342,7 +343,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { pauseCtx->cursorPoint[PAUSE_EQUIP] += 4; // Tunics -> scale - if (pauseCtx->cursorY[PAUSE_EQUIP] == 3 && pauseCtx->cursorX[PAUSE_EQUIP] > 0) { + if (altItems && pauseCtx->cursorY[PAUSE_EQUIP] == 3 && pauseCtx->cursorX[PAUSE_EQUIP] > 0) { pauseCtx->cursorPoint[PAUSE_EQUIP] -= pauseCtx->cursorX[PAUSE_EQUIP]; pauseCtx->cursorX[PAUSE_EQUIP] = 0; } @@ -525,6 +526,9 @@ void KaleidoScope_DrawEquipment(PlayState* play) { u16 buttonsToCheck = BTN_A | BTN_CLEFT | BTN_CDOWN | BTN_CRIGHT; if (CVarGetInteger("gDpadEquips", 0) && (!CVarGetInteger("gDpadPause", 0) || CHECK_BTN_ALL(input->cur.button, BTN_CUP))) { + if (!CVarGetInteger("gAltItemMenu", 0)) { + buttonsToCheck |= BTN_DUP; + } buttonsToCheck |= BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } @@ -692,7 +696,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { point = CUR_UPG_VALUE(sChildUpgrades[i]); if ((point != 0) && (CUR_UPG_VALUE(sChildUpgrades[i]) != 0)) { if (drawGreyItems && - ((sChildUpgradeItemBases[i] + CUR_UPG_VALUE(sChildUpgrades[i]) - 1) == ITEM_GAUNTLETS_SILVER || + ((sChildUpgradeItemBases[i] + CUR_UPG_VALUE(sChildUpgrades[i]) - 1) == ITEM_GAUNTLETS_SILVER || (sChildUpgradeItemBases[i] + CUR_UPG_VALUE(sChildUpgrades[i]) - 1) == ITEM_GAUNTLETS_GOLD)) { // Grey Out the Gauntlets gDPSetGrayscaleColor(POLY_KAL_DISP++, 109, 109, 109, 255); gSPGrayscale(POLY_KAL_DISP++, true); @@ -720,7 +724,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { } } - if (i == 3) { + if (altItems && i == 3) { continue; } 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 aff0f671d0a..ac92d21a730 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 @@ -8,22 +8,8 @@ #include "soh_assets.h" u8 gAmmoItems[] = { - ITEM_NONE, // SLOT_DINS_FIRE - ITEM_BOMB, // SLOT_BOMB - ITEM_BOMBCHU, // SLOT_BOMBCHU - ITEM_NUT, // SLOT_NUT - ITEM_NONE, // SLOT_LENS - ITEM_BEAN, // SLOT_BEAN - ITEM_NONE, // SLOT_FARORES_WIND - ITEM_SLINGSHOT, // SLOT_SLINGSHOT - ITEM_NONE, // SLOT_BOOMERANG - ITEM_STICK, // SLOT_STICK - ITEM_NONE, // SLOT_BOOTS_HOVER - ITEM_NONE, // SLOT_TRADE_CHILD - ITEM_NONE, // SLOT_NAYRUS_LOVE - ITEM_BOW, // SLOT_BOW - ITEM_NONE, // SLOT_HOOKSHOT - ITEM_NONE, // SLOT_HAMMER + ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_SLINGSHOT, ITEM_NONE, + ITEM_BOMBCHU, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_BEAN, ITEM_NONE, }; static s16 sEquipState = 0; @@ -31,27 +17,11 @@ static s16 sEquipAnimTimer = 0; static s16 sEquipMoveTimer = 10; bool gSelectingMask; bool gSelectingAdultTrade; - -ArrowMenuState gArrowMenuState; -static s16 sArrowMenuTimer = 0; +bool gSelectingArrow; /* Maps an inventory slot to double the position of its ammo count in sAmmoVtxTableIdx */ static s16 sAmmoVtxOffset[] = { - 99, // SLOT_DINS_FIRE - 0, // SLOT_BOMB - 2, // SLOT_BOMBCHU - 4, // SLOT_NUT - 99, // SLOT_LENS - 6, // SLOT_BEAN - 99, // SLOT_FARORES_WIND - 8, // SLOT_SLINGSHOT - 99, // SLOT_BOOMERANG - 10, // SLOT_STICK - 99, // SLOT_BOOTS_HOVER - 99, // SLOT_TRADE_CHILD - 99, // SLOT_NAYRUS_LOVE - 12, // SLOT_BOW - 99 // SLOT_HOOKSHOT + 0, 2, 4, 6, 99, 99, 8, 99, 10, 99, 99, 99, 99, 99, 12, }; typedef enum { @@ -63,17 +33,36 @@ typedef enum { extern const char* _gAmmoDigit0Tex[]; +u8 KaleidoScope_ItemInSlot(u8 slot) { + if (CVarGetInteger("gAltItemMenu", 0)) { + slot = gAltToMainSlot[slot]; + } + if (slot < 24) { + return gSaveContext.inventory.items[slot]; + } else if ((slot == SLOT_BOOTS_IRON) && (gSaveContext.inventory.equipment & 1 << 13)) { + return ITEM_BOOTS_IRON; + } else if ((slot == SLOT_BOOTS_HOVER) && (gSaveContext.inventory.equipment & 1 << 14)) { + return ITEM_BOOTS_HOVER; + } else { + return ITEM_NONE; + } +} + void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, s16 item, int slot) { s16 ammo; s16 i; OPEN_DISPS(gfxCtx); + if (item == ITEM_BOW_ARROW_FIRE || item == ITEM_BOW_ARROW_ICE || item == ITEM_BOW_ARROW_LIGHT) { + item = ITEM_BOW; + } + ammo = AMMO(item); gDPPipeSync(POLY_KAL_DISP++); - if (!CHECK_AGE_REQ_SLOT(SLOT(item))) { + if (!CHECK_AGE_REQ_SLOT(KALEIDO_SLOT(item))) { gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 100, 100, 100, pauseCtx->alpha); } else { gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); @@ -81,8 +70,7 @@ void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, if (ammo == 0) { gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 130, 130, 130, pauseCtx->alpha); } else if ((item == ITEM_BOMB && AMMO(item) == CUR_CAPACITY(UPG_BOMB_BAG)) || - ((item == ITEM_BOW || item == ITEM_BOW_ARROW_FIRE || item == ITEM_BOW_ARROW_ICE || item == ITEM_BOW_ARROW_LIGHT) - && AMMO(item) == CUR_CAPACITY(UPG_QUIVER)) || + (item == ITEM_BOW && AMMO(item) == CUR_CAPACITY(UPG_QUIVER)) || (item == ITEM_SLINGSHOT && AMMO(item) == CUR_CAPACITY(UPG_BULLET_BAG)) || (item == ITEM_STICK && AMMO(item) == CUR_CAPACITY(UPG_STICKS)) || (item == ITEM_NUT && AMMO(item) == CUR_CAPACITY(UPG_NUTS)) || (item == ITEM_BOMBCHU && ammo == 50) || @@ -184,7 +172,7 @@ void KaleidoScope_DrawItemCycleExtras(PlayState* play, u8 slot, u8 isCycling, u8 } } - u8 slotItem = gSaveContext.inventory.items[slot]; + u8 slotItem = KaleidoScope_ItemInSlot(slot); u8 showLeftItem = leftItem != ITEM_NONE && slotItem != leftItem; u8 showRightItem = rightItem != ITEM_NONE && slotItem != rightItem && leftItem != rightItem; @@ -261,215 +249,195 @@ void KaleidoScope_DrawItemCycleExtras(PlayState* play, u8 slot, u8 isCycling, u8 CLOSE_DISPS(play->state.gfxCtx); } -void KaleidoScope_SetArrowSelectActive(PauseContext* pauseCtx, bool active) { - if (ARROW_SELECT_OPEN == active) - return; - - gArrowMenuState = AMS_CLOSING + active; - pauseCtx->arrowMenuAnimPos = 12; - sArrowMenuTimer = 2; -} - -void KaleidoScope_ArrowSelect(PlayState* play, u16 cursorSlot) { - PauseContext* pauseCtx = &play->pauseCtx; - if (cursorSlot != SLOT_BOW || !CHECK_AGE_REQ_SLOT(SLOT_BOW)) { - gArrowMenuState = AMS_DISABLED; - pauseCtx->arrowMenuAnimPos = 0; - sArrowMenuTimer = 0; - return; - } +static u8 sBowArrowItems[] = {ITEM_BOW, ITEM_BOW_ARROW_FIRE, ITEM_BOW_ARROW_ICE, ITEM_BOW_ARROW_LIGHT}; +static u8 sArrowItems[] = {ITEM_BOW, ITEM_ARROW_FIRE, ITEM_ARROW_ICE, ITEM_ARROW_LIGHT}; - Input* input = &play->state.input[0]; +// Vertices for the extra items +static Vtx sArrowSelectExtraItemVtx[] = { + // Fire Arrow + VTX(-16, 48, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(16, 48, 0, 32 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-16, 16, 0, 0 << 5, 32 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(16, 16, 0, 32 << 5, 32 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + // Ice Arrow + VTX(-48, 16, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-16, 16, 0, 32 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-48, -16, 0, 0 << 5, 32 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-16, -16, 0, 32 << 5, 32 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + // Light Arrow + VTX(16, 16, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(48, 16, 0, 32 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(16, -16, 0, 0 << 5, 32 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(48, -16, 0, 32 << 5, 32 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + // Arrow + VTX(-16, -16, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(16, -16, 0, 32 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-16, -48, 0, 0 << 5, 32 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(16, -48, 0, 32 << 5, 32 << 5, 0xFF, 0xFF, 0xFF, 0xFF), +}; - // Allow changing arrows if: - // - Selecting bow slot and pressing A - // - You have an item in the bow slot and any magic arrow - if (CHECK_BTN_ALL(input->press.button, BTN_A) && - INV_CONTENT(ITEM_BOW) != ITEM_NONE && - (INV_CONTENT(ITEM_ARROW_FIRE) != ITEM_NONE || - INV_CONTENT(ITEM_ARROW_ICE) != ITEM_NONE || - INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_NONE)) { - Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); - KaleidoScope_SetArrowSelectActive(pauseCtx, !ARROW_SELECT_OPEN); - } +// Vertices for the circle behind the items +static Vtx sArrowSelectCircleVtx[] = { + // Fire Arrow + VTX(-24, 56, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(24, 56, 0, 48 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-24, 8, 0, 0 << 5, 48 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(24, 8, 0, 48 << 5, 48 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + // Ice Arrow + VTX(-56, 24, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-8, 24, 0, 48 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-56, -24, 0, 0 << 5, 48 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-8, -24, 0, 48 << 5, 48 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + // Light Arrow + VTX(8, 24, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(56, 24, 0, 48 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(8, -24, 0, 0 << 5, 48 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(56, -24, 0, 48 << 5, 48 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + // Arrow + VTX(-24, -8, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(24, -8, 0, 48 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-24, -56, 0, 0 << 5, 48 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(24, -56, 0, 48 << 5, 48 << 5, 0xFF, 0xFF, 0xFF, 0xFF), +}; - if (!ARROW_SELECT_OPEN) { - return; - } +static Vtx sArrowSelectIndicatorVtx[] = { + // Fire Arrow + VTX(-18, 56, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(18, 56, 0, 16 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-18, 20, 0, 0 << 5, 16 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(18, 20, 0, 16 << 5, 16 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + // Ice Arrow + VTX(-56, 18, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-20, 18, 0, 16 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-56, -18, 0, 0 << 5, 16 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-20, -18, 0, 16 << 5, 16 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + // Light Arrow + VTX(20, 18, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(56, 18, 0, 16 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(20, -18, 0, 0 << 5, 16 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(56, -18, 0, 16 << 5, 16 << 5, 0xFF, 0xFF, 0xFF, 0xFF), +}; - pauseCtx->cursorColorSet = 8; - bool dpad = CVarGetInteger("gDpadPause", 0); - - // Select arrow with stick/d-pad - // Up = Fire - // Left = Ice - // Right = Light - // Down = Normal - u8 newBow = ITEM_NONE; - u16 arrowCursorSlot; - if (pauseCtx->stickRelY < -30 || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DDOWN))) { - newBow = ITEM_BOW; - arrowCursorSlot = cursorSlot + 6; - } else if (pauseCtx->stickRelY > 30 || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DUP))) { - newBow = (INV_CONTENT(ITEM_ARROW_FIRE) != ITEM_NONE) ? ITEM_BOW_ARROW_FIRE : ITEM_NONE; - arrowCursorSlot = cursorSlot - 6; - } else if (pauseCtx->stickRelX < -30 || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) { - newBow = (INV_CONTENT(ITEM_ARROW_ICE) != ITEM_NONE) ? ITEM_BOW_ARROW_ICE : ITEM_NONE; - arrowCursorSlot = cursorSlot - 1; - } else if (pauseCtx->stickRelX > 30 || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) { - newBow = (INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_NONE) ? ITEM_BOW_ARROW_LIGHT : ITEM_NONE; - arrowCursorSlot = cursorSlot + 1; - } +// Vertices for A button indicator (coordinates 1.5x larger than texture size) +static Vtx sArrowSelectAButtonVtx[] = { + VTX(-18, -20, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(18, -20, 0, 24 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(-18, -44, 0, 0 << 5, 16 << 5, 0xFF, 0xFF, 0xFF, 0xFF), + VTX(18, -44, 0, 24 << 5, 16 << 5, 0xFF, 0xFF, 0xFF, 0xFF), +}; - if (newBow == ITEM_NONE) { - return; - } +void KaleidoScope_DrawArrowSelectExtras(PlayState* play, u8 slot, u8 isSelecting, u8 canSelect) { + PauseContext* pauseCtx = &play->pauseCtx; - // If you double select an arrow, reset to normal - if (newBow == INV_CONTENT(ITEM_BOW)) { - newBow = ITEM_BOW; + OPEN_DISPS(play->state.gfxCtx); - // If double selecting regular arrows, cancel - if (INV_CONTENT(ITEM_BOW) == ITEM_BOW) { - Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); - KaleidoScope_SetArrowSelectActive(pauseCtx, false); - return; + // Update active cycling animation timer + if (isSelecting) { + if (sSlotCycleActiveAnimTimer[slot] < 5) { + sSlotCycleActiveAnimTimer[slot]++; } - } - - u16 sfxId; - if (newBow == ITEM_BOW || CVarGetInteger("gSkipArrowAnimation", 0)) { - sfxId = NA_SE_SY_DECIDE; - pauseCtx->equipTargetItem = newBow; - pauseCtx->equipAnimAlpha = 255; - sEquipState = ES_MAGIC_ARROW_APPLYING; } else { - sfxId = NA_SE_SY_SET_FIRE_ARROW + (newBow - ITEM_BOW_ARROW_FIRE); - pauseCtx->equipTargetItem = 0xBF - ITEM_BOW_ARROW_FIRE + newBow; - pauseCtx->equipAnimAlpha = 0; - sEquipState = ES_MAGIC_ARROW_GLOWING; + if (sSlotCycleActiveAnimTimer[slot] > 0) { + sSlotCycleActiveAnimTimer[slot]--; + } } - Audio_PlaySoundGeneral(sfxId, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); - pauseCtx->equipAnimX = pauseCtx->itemVtx[arrowCursorSlot * 4].v.ob[0] * 10; - pauseCtx->equipAnimY = pauseCtx->itemVtx[arrowCursorSlot * 4].v.ob[1] * 10; - sEquipMoveTimer = 6; - sEquipAnimTimer = 0; - pauseCtx->unk_1E4 = 3; -} + u8 slotItem = KaleidoScope_ItemInSlot(slot); + u8 showFire = INV_CONTENT(ITEM_ARROW_FIRE) != ITEM_NONE; + u8 showIce = INV_CONTENT(ITEM_ARROW_ICE) != ITEM_NONE; + u8 showLight = INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_NONE; -void KaleidoScope_BowMenuSetRect(PauseContext* pauseCtx, s16 xOffset, s16 yOffset, s16 size, u8 vtx) { - s16 bowCenterX = -64 + 16; - s16 bowCenterY = -6 - 16 + pauseCtx->offsetY; - s16 arrowCenterX = bowCenterX + xOffset; - s16 arrowCenterY = bowCenterY + yOffset; - s16 arrowX = arrowCenterX - size / 2; - s16 arrowY = arrowCenterY + size / 2; - - pauseCtx->arrowSelectVtx[vtx].v.ob[0] = pauseCtx->arrowSelectVtx[vtx + 2].v.ob[0] = arrowX; - pauseCtx->arrowSelectVtx[vtx + 1].v.ob[0] = pauseCtx->arrowSelectVtx[vtx + 3].v.ob[0] = arrowX + size; - pauseCtx->arrowSelectVtx[vtx].v.ob[1] = pauseCtx->arrowSelectVtx[vtx + 1].v.ob[1] = arrowY; - pauseCtx->arrowSelectVtx[vtx + 2].v.ob[1] = pauseCtx->arrowSelectVtx[vtx + 3].v.ob[1] = arrowY - size; -} - -void KaleidoScope_DrawBowMenuTexture(PlayState* play, s16 xOffset, s16 yOffset, s16 drawSize, u8 vtx, void* tex, u16 texSize) { - PauseContext* pauseCtx = &play->pauseCtx; + if (canSelect && slotItem != ITEM_NONE && (showFire || showIce || showLight)) { + Matrix_Push(); - KaleidoScope_BowMenuSetRect(pauseCtx, xOffset, yOffset, drawSize, vtx); - pauseCtx->arrowSelectVtx[vtx + 1].v.tc[0] = pauseCtx->arrowSelectVtx[vtx + 2].v.tc[1] = - pauseCtx->arrowSelectVtx[vtx + 3].v.tc[0] = pauseCtx->arrowSelectVtx[vtx + 3].v.tc[1] = texSize << 5; + Vtx* itemTopLeft = &pauseCtx->itemVtx[slot * 4]; + Vtx* itemBottomRight = &itemTopLeft[3]; - OPEN_DISPS(play->state.gfxCtx); + s16 halfX = (itemBottomRight->v.ob[0] - itemTopLeft->v.ob[0]) / 2; + s16 halfY = (itemBottomRight->v.ob[1] - itemTopLeft->v.ob[1]) / 2; - gSPVertex(POLY_KAL_DISP++, &pauseCtx->arrowSelectVtx[vtx], 4, 0); - KaleidoScope_DrawQuadTextureRGBA32(play->state.gfxCtx, tex, texSize, texSize, 0); + Matrix_Translate(itemTopLeft->v.ob[0] + halfX, itemTopLeft->v.ob[1] + halfY, 0, MTXMODE_APPLY); - CLOSE_DISPS(play->state.gfxCtx); -} + f32 animScale = (f32)(5 - sSlotCycleActiveAnimTimer[slot]) / 5; -void KaleidoScope_DrawMagicArrowIcon(PlayState* play, s16 offset, u8 itemId) { - if (INV_CONTENT(itemId) == ITEM_NONE || !CHECK_AGE_REQ_SLOT(SLOT_BOW)) { - return; - } + // When not selecting or actively animating, shrink and move the items under the main slot item + if (!isSelecting || sSlotCycleActiveAnimTimer[slot] < 5) { + f32 finalScale = 1.0f - (0.675f * animScale); + Matrix_Scale(finalScale, finalScale, 1.0f, MTXMODE_APPLY); + } - s16 xOffset, yOffset, vtx; - char* source; - switch (itemId) { - case ITEM_ARROW_FIRE: - xOffset = 0; - yOffset = offset; - vtx = 0; - source = gFireArrowPowerTex; - break; - case ITEM_ARROW_ICE: - xOffset = -offset; - yOffset = 0; - vtx = 4; - source = gIceArrowPowerTex; - break; - case ITEM_ARROW_LIGHT: - xOffset = offset; - yOffset = 0; - vtx = 8; - source = gLightArrowPowerTex; - break; - default: - return; - } + gSPMatrix(POLY_KAL_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - KaleidoScope_DrawBowMenuTexture(play, xOffset, yOffset, 12, vtx, source, 16); -} + // Render A button indicator when hovered and not cycling + if (!isSelecting && sSlotCycleActiveAnimTimer[slot] == 0 && pauseCtx->cursorSlot[PAUSE_ITEM] == slot && + pauseCtx->cursorSpecialPos == 0) { + Color_RGB8 aButtonColor = { 0, 100, 255 }; + if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) { + aButtonColor = CVarGetColor24("gCosmetics.Hud_AButton.Value", aButtonColor); + } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) { + aButtonColor = (Color_RGB8){ 0, 255, 100 }; + } -void KaleidoScope_DrawSelectableArrow(PlayState* play, s16 offset, u8 itemId) { - if (INV_CONTENT(itemId) == ITEM_NONE || !CHECK_AGE_REQ_SLOT(SLOT_BOW)) { - return; - } + gSPVertex(POLY_KAL_DISP++, sArrowSelectAButtonVtx, 4, 0); + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, aButtonColor.r, aButtonColor.g, aButtonColor.b, pauseCtx->alpha); + gDPLoadTextureBlock(POLY_KAL_DISP++, gABtnSymbolTex, G_IM_FMT_IA, G_IM_SIZ_8b, 24, 16, 0, + G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 4, 4, G_TX_NOLOD, G_TX_NOLOD); + gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0); + } - s16 xOffset, yOffset, vtx; - char* tex = gItemIcons[itemId]; - switch (itemId) { - case ITEM_ARROW_FIRE: - xOffset = 0; - yOffset = offset; - vtx = 0; - break; - case ITEM_ARROW_ICE: - xOffset = -offset; - yOffset = 0; - vtx = 4; - break; - case ITEM_ARROW_LIGHT: - xOffset = offset; - yOffset = 0; - vtx = 8; - break; - case ITEM_BOW: - xOffset = 0; - yOffset = -offset; - vtx = 12; - tex = gArrowIconTex; - break; - default: - return; - } + // Render a dark circle behind the arrows when selecting + if (isSelecting) { + gSPVertex(POLY_KAL_DISP++, sArrowSelectCircleVtx, 16, 0); + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 0, 0, 0, pauseCtx->alpha * (1.0f - animScale)); + gDPLoadTextureBlock_4b(POLY_KAL_DISP++, gPausePromptCursorTex, G_IM_FMT_I, 48, 48, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, + G_TX_NOLOD, G_TX_NOLOD); - if (gArrowMenuState == AMS_ENABLED) { - PauseContext* pauseCtx = &play->pauseCtx; - OPEN_DISPS(play->state.gfxCtx); - gDPPipeSync(POLY_KAL_DISP++); - vtx += 16; + if (showFire) { + gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0); + } + if (showIce) { + gSP1Quadrangle(POLY_KAL_DISP++, 4, 6, 7, 5, 0); + } + if (showLight) { + gSP1Quadrangle(POLY_KAL_DISP++, 8, 10, 11, 9, 0); + } + gSP1Quadrangle(POLY_KAL_DISP++, 12, 14, 15, 13, 0); + } - gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); - gDPSetEnvColor(POLY_KAL_DISP++, 0, 0, 0, 0); - KaleidoScope_BowMenuSetRect(pauseCtx, xOffset, yOffset, 32, vtx); - gSPVertex(POLY_KAL_DISP++, &pauseCtx->arrowSelectVtx[vtx], 4, 0); - POLY_KAL_DISP = KaleidoScope_QuadTextureIA8(POLY_KAL_DISP, gEquippedItemOutlineTex, 32, 32, 0); + if (isSelecting || sSlotCycleActiveAnimTimer[slot] != 0) { + // Render arrows + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); + gSPVertex(POLY_KAL_DISP++, sArrowSelectExtraItemVtx, 16, 0); + if (showFire) { + KaleidoScope_DrawQuadTextureRGBA32(play->state.gfxCtx, gItemIcons[ITEM_ARROW_FIRE], 32, 32, 0); + } + if (showIce) { + KaleidoScope_DrawQuadTextureRGBA32(play->state.gfxCtx, gItemIcons[ITEM_ARROW_ICE], 32, 32, 4); + } + if (showLight) { + KaleidoScope_DrawQuadTextureRGBA32(play->state.gfxCtx, gItemIcons[ITEM_ARROW_LIGHT], 32, 32, 8); + } + KaleidoScope_DrawQuadTextureRGBA32(play->state.gfxCtx, gArrowIconTex, 32, 32, 12); + } else { + // Render arrows + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); + gSPVertex(POLY_KAL_DISP++, sArrowSelectIndicatorVtx, 12, 0); + if (showFire) { + KaleidoScope_DrawQuadTextureRGBA32(play->state.gfxCtx, gFireArrowPowerTex, 16, 16, 0); + } + if (showIce) { + KaleidoScope_DrawQuadTextureRGBA32(play->state.gfxCtx, gIceArrowPowerTex, 16, 16, 4); + } + if (showLight) { + KaleidoScope_DrawQuadTextureRGBA32(play->state.gfxCtx, gLightArrowPowerTex, 16, 16, 8); + } + } - vtx -= 16; - CLOSE_DISPS(play->state.gfxCtx); + Matrix_Pop(); } - KaleidoScope_DrawBowMenuTexture(play, xOffset, yOffset, 28, vtx, tex, 32); + CLOSE_DISPS(play->state.gfxCtx); } void KaleidoScope_DrawItemSelect(PlayState* play) { @@ -491,6 +459,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { bool dpad = (CVarGetInteger("gDpadPause", 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); bool pauseAnyCursor = (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); + bool altItemMenu = CVarGetInteger("gAltItemMenu", 0); // only allow mask select when: // the shop is open: @@ -502,6 +471,12 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER) && Flags_GetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD); + bool canArrowSelect = altItemMenu && + INV_CONTENT(ITEM_BOW) != ITEM_NONE && + (INV_CONTENT(ITEM_ARROW_FIRE) != ITEM_NONE || + INV_CONTENT(ITEM_ARROW_ICE) != ITEM_NONE || + INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_NONE); + OPEN_DISPS(play->state.gfxCtx); Gfx_SetupDL_42Opa(play->state.gfxCtx); @@ -512,7 +487,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { pauseCtx->nameColorSet = 0; if ((pauseCtx->state == 6) && (pauseCtx->unk_1E4 == 0) && (pauseCtx->pageIndex == PAUSE_ITEM)) { - moveCursorResult = 0 || ARROW_SELECT_OPEN || gSelectingMask || gSelectingAdultTrade; + moveCursorResult = 0 || gSelectingMask || gSelectingAdultTrade || gSelectingArrow; oldCursorPoint = pauseCtx->cursorPoint[PAUSE_ITEM]; cursorItem = pauseCtx->cursorItem[PAUSE_ITEM]; @@ -534,14 +509,14 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { // Seem necessary to match if (pauseCtx->cursorX[PAUSE_ITEM]) {} - if (gSaveContext.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]]) {} + if (KaleidoScope_ItemInSlot(pauseCtx->cursorPoint[PAUSE_ITEM])) {} while (moveCursorResult == 0) { if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) { if (pauseCtx->cursorX[PAUSE_ITEM] != 0) { pauseCtx->cursorX[PAUSE_ITEM] -= 1; pauseCtx->cursorPoint[PAUSE_ITEM] -= 1; - if ((gSaveContext.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] != ITEM_NONE) || + if ((KaleidoScope_ItemInSlot(pauseCtx->cursorPoint[PAUSE_ITEM]) != ITEM_NONE) || pauseAnyCursor) { moveCursorResult = 1; } @@ -573,7 +548,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { if (pauseCtx->cursorX[PAUSE_ITEM] < 5) { pauseCtx->cursorX[PAUSE_ITEM] += 1; pauseCtx->cursorPoint[PAUSE_ITEM] += 1; - if ((gSaveContext.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] != ITEM_NONE) || + if ((KaleidoScope_ItemInSlot(pauseCtx->cursorPoint[PAUSE_ITEM]) != ITEM_NONE) || pauseAnyCursor) { moveCursorResult = 1; } @@ -605,7 +580,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { } if (moveCursorResult == 1) { - cursorItem = gSaveContext.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]]; + cursorItem = KaleidoScope_ItemInSlot(pauseCtx->cursorPoint[PAUSE_ITEM]); } osSyncPrintf("【X cursor=%d(%) (cur_xpt=%d)(ok_fg=%d)(ccc=%d)(key_angle=%d)】 ", @@ -621,7 +596,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { cursorPoint = cursorX = cursorY = 0; while (true) { - if (gSaveContext.inventory.items[cursorPoint] != ITEM_NONE) { + if (KaleidoScope_ItemInSlot(cursorPoint) != ITEM_NONE) { pauseCtx->cursorPoint[PAUSE_ITEM] = cursorPoint; pauseCtx->cursorX[PAUSE_ITEM] = cursorX; pauseCtx->cursorY[PAUSE_ITEM] = cursorY; @@ -656,7 +631,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { cursorPoint = cursorX = 5; cursorY = 0; while (true) { - if (gSaveContext.inventory.items[cursorPoint] != ITEM_NONE) { + if (KaleidoScope_ItemInSlot(cursorPoint) != ITEM_NONE) { pauseCtx->cursorPoint[PAUSE_ITEM] = cursorPoint; pauseCtx->cursorX[PAUSE_ITEM] = cursorX; pauseCtx->cursorY[PAUSE_ITEM] = cursorY; @@ -686,7 +661,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { if (pauseCtx->cursorSpecialPos == 0) { if (cursorItem != PAUSE_ITEM_NONE) { if ((ABS(pauseCtx->stickRelY) > 30) || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DDOWN | BTN_DUP))) { - moveCursorResult = 0 || ARROW_SELECT_OPEN || gSelectingMask || gSelectingAdultTrade; + moveCursorResult = 0 || gSelectingMask || gSelectingAdultTrade || gSelectingArrow; cursorPoint = pauseCtx->cursorPoint[PAUSE_ITEM]; cursorY = pauseCtx->cursorY[PAUSE_ITEM]; @@ -695,7 +670,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { if (pauseCtx->cursorY[PAUSE_ITEM] != 0) { pauseCtx->cursorY[PAUSE_ITEM] -= 1; pauseCtx->cursorPoint[PAUSE_ITEM] -= 6; - if ((gSaveContext.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] != ITEM_NONE) || + if ((KaleidoScope_ItemInSlot(pauseCtx->cursorPoint[PAUSE_ITEM]) != ITEM_NONE) || pauseAnyCursor) { moveCursorResult = 1; } @@ -709,7 +684,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { if (pauseCtx->cursorY[PAUSE_ITEM] < 3) { pauseCtx->cursorY[PAUSE_ITEM] += 1; pauseCtx->cursorPoint[PAUSE_ITEM] += 6; - if ((gSaveContext.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] != ITEM_NONE) || + if ((KaleidoScope_ItemInSlot(pauseCtx->cursorPoint[PAUSE_ITEM]) != ITEM_NONE) || pauseAnyCursor) { moveCursorResult = 1; } @@ -734,9 +709,9 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { pauseCtx->cursorColorSet = 4; if (moveCursorResult == 1) { - cursorItem = gSaveContext.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]]; + cursorItem = KaleidoScope_ItemInSlot(pauseCtx->cursorPoint[PAUSE_ITEM]); } else if (moveCursorResult != 2) { - cursorItem = gSaveContext.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]]; + cursorItem = KaleidoScope_ItemInSlot(pauseCtx->cursorPoint[PAUSE_ITEM]); } pauseCtx->cursorItem[PAUSE_ITEM] = cursorItem; @@ -751,7 +726,9 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { KaleidoScope_SetCursorVtx(pauseCtx, index, pauseCtx->itemVtx); if ((pauseCtx->debugState == 0) && (pauseCtx->state == 6) && (pauseCtx->unk_1E4 == 0)) { - if (canMaskSelect && cursorSlot == SLOT_TRADE_CHILD && CHECK_BTN_ALL(input->press.button, BTN_A)) { + if (canMaskSelect && cursorSlot == (altItemMenu ? SLOT_ALT_TRADE_CHILD : SLOT_TRADE_CHILD) && + CHECK_BTN_ALL(input->press.button, BTN_A) + ) { Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); gSelectingMask = !gSelectingMask; } @@ -787,7 +764,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { } } } - gSelectingMask = cursorSlot == SLOT_TRADE_CHILD; + gSelectingMask = cursorSlot == (altItemMenu ? SLOT_ALT_TRADE_CHILD : SLOT_TRADE_CHILD); gSlotAgeReqs[SLOT_TRADE_CHILD] = gItemAgeReqs[ITEM_MASK_BUNNY] = ((((CVarGetInteger("gMMBunnyHood", BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) && CVarGetInteger("gAdultBunnyHood", 0)) || CVarGetInteger("gTimelessEquipment", 0)) && @@ -796,7 +773,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { : AGE_REQ_CHILD; } if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) && - cursorSlot == SLOT_TRADE_ADULT && CHECK_BTN_ALL(input->press.button, BTN_A)) { + cursorSlot == (altItemMenu ? SLOT_ALT_TRADE_ADULT : SLOT_TRADE_ADULT) && CHECK_BTN_ALL(input->press.button, BTN_A)) { Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); gSelectingAdultTrade = !gSelectingAdultTrade; } @@ -811,13 +788,76 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); Inventory_ReplaceItem(play, INV_CONTENT(ITEM_TRADE_ADULT), Randomizer_GetPrevAdultTradeItem()); } - gSelectingAdultTrade = cursorSlot == SLOT_TRADE_ADULT; + gSelectingAdultTrade = cursorSlot == (altItemMenu ? SLOT_ALT_TRADE_ADULT : SLOT_TRADE_ADULT); } + if (canArrowSelect && cursorSlot == SLOT_ALT_BOW && CHECK_BTN_ALL(input->press.button, BTN_A)) { + Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + gSelectingArrow = !gSelectingArrow; + } + if (gSelectingArrow) { + pauseCtx->cursorColorSet = 8; + + // Select arrow with stick/d-pad + // Up = Fire + // Left = Ice + // Right = Light + // Down = Normal + u8 newBow = ITEM_NONE; + u16 arrowCursorSlot; + if (pauseCtx->stickRelY < -30 || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DDOWN))) { + newBow = ITEM_BOW; + arrowCursorSlot = cursorSlot + 6; + } else if (pauseCtx->stickRelY > 30 || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DUP))) { + newBow = (INV_CONTENT(ITEM_ARROW_FIRE) != ITEM_NONE) ? ITEM_BOW_ARROW_FIRE : ITEM_NONE; + arrowCursorSlot = cursorSlot - 6; + } else if (pauseCtx->stickRelX < -30 || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) { + newBow = (INV_CONTENT(ITEM_ARROW_ICE) != ITEM_NONE) ? ITEM_BOW_ARROW_ICE : ITEM_NONE; + arrowCursorSlot = cursorSlot - 1; + } else if (pauseCtx->stickRelX > 30 || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) { + newBow = (INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_NONE) ? ITEM_BOW_ARROW_LIGHT : ITEM_NONE; + arrowCursorSlot = cursorSlot + 1; + } - KaleidoScope_ArrowSelect(play, cursorSlot); + // If you double select an arrow, reset to normal + if (newBow == INV_CONTENT(ITEM_BOW)) { + newBow = ITEM_BOW; + } + + // If double selecting regular arrows, cancel + if (newBow == ITEM_BOW && INV_CONTENT(ITEM_BOW) == ITEM_BOW) { + Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + gSelectingArrow = false; + newBow = ITEM_NONE; + } + + if (newBow != ITEM_NONE) { + u16 sfxId; + if (newBow == ITEM_BOW || CVarGetInteger("gSkipArrowAnimation", 0)) { + sfxId = NA_SE_SY_DECIDE; + pauseCtx->equipTargetItem = newBow; + pauseCtx->equipAnimAlpha = 255; + sEquipState = ES_MAGIC_ARROW_APPLYING; + } else { + sfxId = NA_SE_SY_SET_FIRE_ARROW + (newBow - ITEM_BOW_ARROW_FIRE); + pauseCtx->equipTargetItem = 0xBF - ITEM_BOW_ARROW_FIRE + newBow; + pauseCtx->equipAnimAlpha = 0; + sEquipState = ES_MAGIC_ARROW_GLOWING; + } + + Audio_PlaySoundGeneral(sfxId, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + pauseCtx->equipAnimX = pauseCtx->itemVtx[arrowCursorSlot * 4].v.ob[0] * 10; + pauseCtx->equipAnimY = pauseCtx->itemVtx[arrowCursorSlot * 4].v.ob[1] * 10; + sEquipMoveTimer = 6; + sEquipAnimTimer = 0; + pauseCtx->unk_1E4 = 3; + } + } u16 buttonsToCheck = BTN_CLEFT | BTN_CDOWN | BTN_CRIGHT; if (CVarGetInteger("gDpadEquips", 0) && (!CVarGetInteger("gDpadPause", 0) || CHECK_BTN_ALL(input->cur.button, BTN_CUP))) { + if (!altItemMenu) { + buttonsToCheck |= BTN_DUP; + } buttonsToCheck |= BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; } if (CHECK_BTN_ANY(input->press.button, buttonsToCheck)) { @@ -858,10 +898,13 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { for (i = 0, j = 24 * 4; i < ARRAY_COUNT(gSaveContext.equips.cButtonSlots); i++, j += 4) { u8 buttonItem = gSaveContext.equips.buttonItems[i + 1]; - if ((buttonItem != ITEM_NONE) && // equipped - (buttonItem < ARRAY_COUNT(gItemSlots)) && // has an assigned slot - (gItemSlots[buttonItem] < 24) && // assigned slot is on the menu - !((buttonItem >= ITEM_SHIELD_DEKU) && (buttonItem <= ITEM_BOOTS_KOKIRI))) { // not equipment (except boots) + u8 drawBg = (buttonItem != ITEM_NONE) && // equipped + !((buttonItem >= ITEM_SHIELD_DEKU) && (buttonItem <= ITEM_BOOTS_HOVER)); // not equipment + u8 drawBgAlt = (buttonItem != ITEM_NONE) && // equipped + (buttonItem < ARRAY_COUNT(gAltItemSlots)) && // has an assigned slot + (gAltItemSlots[buttonItem] < 24) && // assigned slot is on the menu + !((buttonItem >= ITEM_SHIELD_DEKU) && (buttonItem <= ITEM_BOOTS_KOKIRI)); // not equipment (except boots) + if (altItemMenu ? drawBgAlt : drawBg) { gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[j], 4, 0); POLY_KAL_DISP = KaleidoScope_QuadTextureIA8(POLY_KAL_DISP, gEquippedItemOutlineTex, 32, 32, 0); } @@ -873,24 +916,43 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { for (i = j = 0; i < 24; i++, j += 4) { gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); - if ((gSaveContext.inventory.items[i] != ITEM_NONE)) { - if ((pauseCtx->unk_1E4 == 0) && (pauseCtx->pageIndex == PAUSE_ITEM) && - (pauseCtx->cursorSpecialPos == 0) && CHECK_AGE_REQ_SLOT(i) && (i == cursorSlot)) { - pauseCtx->itemVtx[j + 0].v.ob[0] = pauseCtx->itemVtx[j + 2].v.ob[0] = - pauseCtx->itemVtx[j + 0].v.ob[0] - 2; + if (KaleidoScope_ItemInSlot(i) != ITEM_NONE) { + if ((pauseCtx->unk_1E4 == 0) && (pauseCtx->pageIndex == PAUSE_ITEM) && (pauseCtx->cursorSpecialPos == 0)) { + if (CHECK_AGE_REQ_SLOT(i)) { + if ((sEquipState == ES_MAGIC_ARROW_EQUIPPING) && (i == SLOT_BOW) && !altItemMenu) { + gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, magicArrowEffectsR[pauseCtx->equipTargetItem - 0xBF], + magicArrowEffectsG[pauseCtx->equipTargetItem - 0xBF], + magicArrowEffectsB[pauseCtx->equipTargetItem - 0xBF], pauseCtx->alpha); + + pauseCtx->itemVtx[j + 0].v.ob[0] = pauseCtx->itemVtx[j + 2].v.ob[0] = + pauseCtx->itemVtx[j + 0].v.ob[0] - 2; - pauseCtx->itemVtx[j + 1].v.ob[0] = pauseCtx->itemVtx[j + 3].v.ob[0] = - pauseCtx->itemVtx[j + 0].v.ob[0] + 32; + pauseCtx->itemVtx[j + 1].v.ob[0] = pauseCtx->itemVtx[j + 3].v.ob[0] = + pauseCtx->itemVtx[j + 0].v.ob[0] + 32; - pauseCtx->itemVtx[j + 0].v.ob[1] = pauseCtx->itemVtx[j + 1].v.ob[1] = - pauseCtx->itemVtx[j + 0].v.ob[1] + 2; + pauseCtx->itemVtx[j + 0].v.ob[1] = pauseCtx->itemVtx[j + 1].v.ob[1] = + pauseCtx->itemVtx[j + 0].v.ob[1] + 2; - pauseCtx->itemVtx[j + 2].v.ob[1] = pauseCtx->itemVtx[j + 3].v.ob[1] = - pauseCtx->itemVtx[j + 0].v.ob[1] - 32; + pauseCtx->itemVtx[j + 2].v.ob[1] = pauseCtx->itemVtx[j + 3].v.ob[1] = + pauseCtx->itemVtx[j + 0].v.ob[1] - 32; + } else if (i == cursorSlot) { + pauseCtx->itemVtx[j + 0].v.ob[0] = pauseCtx->itemVtx[j + 2].v.ob[0] = + pauseCtx->itemVtx[j + 0].v.ob[0] - 2; + + pauseCtx->itemVtx[j + 1].v.ob[0] = pauseCtx->itemVtx[j + 3].v.ob[0] = + pauseCtx->itemVtx[j + 0].v.ob[0] + 32; + + pauseCtx->itemVtx[j + 0].v.ob[1] = pauseCtx->itemVtx[j + 1].v.ob[1] = + pauseCtx->itemVtx[j + 0].v.ob[1] + 2; + + pauseCtx->itemVtx[j + 2].v.ob[1] = pauseCtx->itemVtx[j + 3].v.ob[1] = + pauseCtx->itemVtx[j + 0].v.ob[1] - 32; + } + } } gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[j + 0], 4, 0); - int itemId = gSaveContext.inventory.items[i]; + int itemId = KaleidoScope_ItemInSlot(i); bool not_acquired = !CHECK_AGE_REQ_ITEM(itemId); if (not_acquired) { gDPSetGrayscaleColor(POLY_KAL_DISP++, 109, 109, 109, 255); @@ -917,46 +979,17 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { } // Adult trade item cycle - KaleidoScope_DrawItemCycleExtras(play, SLOT_TRADE_ADULT, gSelectingAdultTrade, + KaleidoScope_DrawItemCycleExtras(play, altItemMenu ? SLOT_ALT_TRADE_ADULT : SLOT_TRADE_ADULT, + gSelectingAdultTrade, IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE), Randomizer_GetPrevAdultTradeItem(), Randomizer_GetNextAdultTradeItem()); // Child mask item cycle (mimics the left/right item behavior from the cycling logic above) u8 childTradeItem = INV_CONTENT(ITEM_TRADE_CHILD); - KaleidoScope_DrawItemCycleExtras(play, SLOT_TRADE_CHILD, gSelectingMask, canMaskSelect, + KaleidoScope_DrawItemCycleExtras(play, altItemMenu ? SLOT_ALT_TRADE_CHILD : SLOT_TRADE_CHILD, + gSelectingMask, canMaskSelect, childTradeItem <= ITEM_MASK_KEATON ? ITEM_MASK_TRUTH : childTradeItem - 1, childTradeItem >= ITEM_MASK_TRUTH ? ITEM_MASK_KEATON : childTradeItem + 1); - - gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); - if (gArrowMenuState == AMS_DISABLED) { - s16 offset = 14; - KaleidoScope_DrawMagicArrowIcon(play, offset, ITEM_ARROW_FIRE); - KaleidoScope_DrawMagicArrowIcon(play, offset, ITEM_ARROW_ICE); - KaleidoScope_DrawMagicArrowIcon(play, offset, ITEM_ARROW_LIGHT); - } else { - s16 offset; - if (gArrowMenuState == AMS_ENABLED) { - offset = 32; - } else { - offset = pauseCtx->arrowMenuAnimPos / sArrowMenuTimer; - pauseCtx->arrowMenuAnimPos -= offset; - if (gArrowMenuState == AMS_OPENING) { - offset = 32 - pauseCtx->arrowMenuAnimPos; - } else { - offset = 20 + pauseCtx->arrowMenuAnimPos; - } - } - - KaleidoScope_DrawSelectableArrow(play, offset, ITEM_ARROW_FIRE); - KaleidoScope_DrawSelectableArrow(play, offset, ITEM_ARROW_ICE); - KaleidoScope_DrawSelectableArrow(play, offset, ITEM_ARROW_LIGHT); - KaleidoScope_DrawSelectableArrow(play, offset, ITEM_BOW); - - sArrowMenuTimer--; - - if (sArrowMenuTimer == 0) { - gArrowMenuState &= 1; - } - } + KaleidoScope_DrawArrowSelectExtras(play, SLOT_ALT_BOW, gSelectingArrow, canArrowSelect); CLOSE_DISPS(play->state.gfxCtx); } @@ -966,7 +999,8 @@ void KaleidoScope_SetupItemEquip(PlayState* play, u16 item, u16 slot, s16 animX, PauseContext* pauseCtx = &play->pauseCtx; gSelectingMask = false; gSelectingAdultTrade = false; - KaleidoScope_SetArrowSelectActive(pauseCtx, false); + gSelectingArrow = false; + int altItemMenu = CVarGetInteger("gAltItemMenu", 0); if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) { pauseCtx->equipTargetCBtn = 0; @@ -975,10 +1009,9 @@ void KaleidoScope_SetupItemEquip(PlayState* play, u16 item, u16 slot, s16 animX, } else if (CHECK_BTN_ALL(input->press.button, BTN_CRIGHT)) { pauseCtx->equipTargetCBtn = 2; } else if (CVarGetInteger("gDpadEquips", 0)) { - // D up is permanently mapped to ocarina - /*if (CHECK_BTN_ALL(input->press.button, BTN_DUP)) { + if (CHECK_BTN_ALL(input->press.button, BTN_DUP) && !altItemMenu) { pauseCtx->equipTargetCBtn = 3; - } else */if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { + } else if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { pauseCtx->equipTargetCBtn = 4; } else if (CHECK_BTN_ALL(input->press.button, BTN_DLEFT)) { pauseCtx->equipTargetCBtn = 5; @@ -988,7 +1021,7 @@ void KaleidoScope_SetupItemEquip(PlayState* play, u16 item, u16 slot, s16 animX, } pauseCtx->equipTargetItem = item; - pauseCtx->equipTargetSlot = slot; + pauseCtx->equipTargetSlot = altItemMenu ? gAltToMainSlot[slot] : slot; pauseCtx->unk_1E4 = 3; pauseCtx->equipAnimX = animX; pauseCtx->equipAnimY = animY; @@ -1085,8 +1118,8 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { { C_DOWN_BUTTON_X+X_Margins_CD, C_DOWN_BUTTON_Y+Y_Margins_CD }, { C_RIGHT_BUTTON_X+X_Margins_CR, C_RIGHT_BUTTON_Y+Y_Margins_CR }, { DPAD_UP_X+X_Margins_DPad_Items, DPAD_UP_Y+Y_Margins_DPad_Items }, - { DPAD_DOWN_X+X_Margins_DPad_Items, DPAD_DOWN_Y+Y_Margins_DPad_Items }, - { DPAD_LEFT_X+X_Margins_DPad_Items, DPAD_LEFT_Y+Y_Margins_DPad_Items }, + { DPAD_DOWN_X+X_Margins_DPad_Items, DPAD_DOWN_Y+Y_Margins_DPad_Items }, + { DPAD_LEFT_X+X_Margins_DPad_Items, DPAD_LEFT_Y+Y_Margins_DPad_Items }, { DPAD_RIGHT_X+X_Margins_DPad_Items, DPAD_RIGHT_Y+Y_Margins_DPad_Items } }; s16 DPad_ItemsOffset[4][2] = { @@ -1204,8 +1237,27 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { return; } + int altItemMenu = CVarGetInteger("gAltItemMenu", 0); + int vtx = 4 * (altItemMenu ? SLOT_ALT_BOW : SLOT_BOW); + if (sEquipState == ES_MAGIC_ARROW_EQUIPPING && !altItemMenu) { + D_8082A488--; + + if (D_8082A488 == 0) { + pauseCtx->equipTargetItem -= 0xBF - ITEM_BOW_ARROW_FIRE; + if (!CVarGetInteger("gSeparateArrows", 0)) { + pauseCtx->equipTargetSlot = SLOT_BOW; + } + sEquipMoveTimer = 6; + WREG(90) = 320; + WREG(87) = WREG(91); + sEquipState++; + Audio_PlaySoundGeneral(NA_SE_SY_SYNTH_MAGIC_ARROW, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + } + return; + } + if (sEquipState == ES_MAGIC_ARROW_APPLYING) { - bowItemVtx = &pauseCtx->itemVtx[52]; + bowItemVtx = &pauseCtx->itemVtx[vtx]; offsetX = ABS(pauseCtx->equipAnimX - bowItemVtx->v.ob[0] * 10) / sEquipMoveTimer; offsetY = ABS(pauseCtx->equipAnimY - bowItemVtx->v.ob[1] * 10) / sEquipMoveTimer; } else { @@ -1227,13 +1279,13 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { WREG(87) -= WREG(87) / sEquipMoveTimer; if (sEquipState == ES_MAGIC_ARROW_APPLYING) { - if (pauseCtx->equipAnimX >= (pauseCtx->itemVtx[52].v.ob[0] * 10)) { + if (pauseCtx->equipAnimX >= (pauseCtx->itemVtx[vtx].v.ob[0] * 10)) { pauseCtx->equipAnimX -= offsetX; } else { pauseCtx->equipAnimX += offsetX; } - if (pauseCtx->equipAnimY >= (pauseCtx->itemVtx[52].v.ob[1] * 10)) { + if (pauseCtx->equipAnimY >= (pauseCtx->itemVtx[vtx].v.ob[1] * 10)) { pauseCtx->equipAnimY -= offsetY; } else { pauseCtx->equipAnimY += offsetY; @@ -1256,18 +1308,43 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { if (sEquipMoveTimer == 0) { if (sEquipState == ES_MAGIC_ARROW_APPLYING) { - pauseCtx->unk_1E4 = 0; - s16 magicArrowType = pauseCtx->equipTargetItem - 0xBF; - if (magicArrowType >= 0 && magicArrowType <= 2) { - pauseCtx->equipTargetItem = ITEM_BOW_ARROW_FIRE + magicArrowType; + if (altItemMenu) { + pauseCtx->unk_1E4 = 0; + s16 magicArrowType = pauseCtx->equipTargetItem - 0xBF; + if (magicArrowType >= 0 && magicArrowType <= 2) { + pauseCtx->equipTargetItem = ITEM_BOW_ARROW_FIRE + magicArrowType; + } + Inventory_ReplaceItem(play, INV_CONTENT(ITEM_BOW), pauseCtx->equipTargetItem); + gSelectingArrow = false; + } else { + sEquipState = ES_MAGIC_ARROW_EQUIPPING; + D_8082A488 = 4; } - Inventory_ReplaceItem(play, INV_CONTENT(ITEM_BOW), pauseCtx->equipTargetItem); - KaleidoScope_SetArrowSelectActive(pauseCtx, false); return; } osSyncPrintf("\n================================\n"); + // Skipping the arrow animation: need to change the item's type and + // slot when it hits the button since it didn't get set earlier + if (pauseCtx->equipTargetItem == ITEM_ARROW_FIRE || pauseCtx->equipTargetItem == ITEM_ARROW_ICE || + pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT) { + switch (pauseCtx->equipTargetItem) { + case ITEM_ARROW_FIRE: + pauseCtx->equipTargetItem = ITEM_BOW_ARROW_FIRE; + break; + case ITEM_ARROW_ICE: + pauseCtx->equipTargetItem = ITEM_BOW_ARROW_ICE; + break; + case ITEM_ARROW_LIGHT: + pauseCtx->equipTargetItem = ITEM_BOW_ARROW_LIGHT; + break; + } + if (!CVarGetInteger("gSeparateArrows", 0)) { + pauseCtx->equipTargetSlot = SLOT_BOW; + } + } + // If the item is on another button already, swap the two uint16_t targetButtonIndex = pauseCtx->equipTargetCBtn + 1; for (uint16_t otherSlotIndex = 0; otherSlotIndex < ARRAY_COUNT(gSaveContext.equips.cButtonSlots); @@ -1314,6 +1391,16 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { } } + const bool ddown = 5; + if (CVarGetInteger("gMapOnDDown", 0) && + pauseCtx->equipTargetCBtn == ddown && + gSaveContext.equips.buttonItems[ddown + 1] == pauseCtx->equipTargetItem && + gSaveContext.equips.cButtonSlots[ddown] == pauseCtx->equipTargetSlot + ) { + pauseCtx->equipTargetItem = ITEM_NONE; + pauseCtx->equipTargetSlot = SLOT_NONE; + } + gSaveContext.equips.buttonItems[targetButtonIndex] = pauseCtx->equipTargetItem; gSaveContext.equips.cButtonSlots[pauseCtx->equipTargetCBtn] = pauseCtx->equipTargetSlot; Interface_LoadItemIcon1(play, targetButtonIndex); @@ -1334,4 +1421,5 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { void KaleidoScope_ResetTradeSelect() { gSelectingMask = false; gSelectingAdultTrade = false; + gSelectingArrow = false; } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h index 19caf918f2f..364d491312a 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h @@ -12,14 +12,7 @@ extern u8 gSlotAgeReqs[]; extern u8 gItemAgeReqs[]; extern u8 gAreaGsFlags[]; extern bool gSelectingMask; -typedef enum { - AMS_DISABLED, - AMS_ENABLED, - AMS_CLOSING, - AMS_OPENING -} ArrowMenuState; -extern ArrowMenuState gArrowMenuState; -#define ARROW_SELECT_OPEN (gArrowMenuState & 1) +extern bool gSelectingArrow; #define MAP_48x85_TEX_WIDTH 48 #define MAP_48x85_TEX_HEIGHT 85 @@ -30,7 +23,6 @@ extern ArrowMenuState gArrowMenuState; #define AGE_REQ_NONE 9 #define CHECK_AGE_REQ_EQUIP(i, j) (CVarGetInteger("gTimelessEquipment", 0) || (gEquipAgeReqs[i][j] == AGE_REQ_NONE) || (gEquipAgeReqs[i][j] == ((void)0, gSaveContext.linkAge))) -#define CHECK_AGE_REQ_SLOT(slotIndex) (CVarGetInteger("gTimelessEquipment", 0) || (gSlotAgeReqs[slotIndex] == AGE_REQ_NONE) || gSlotAgeReqs[slotIndex] == ((void)0, gSaveContext.linkAge)) #define CHECK_AGE_REQ_ITEM(itemIndex) (CVarGetInteger("gTimelessEquipment", 0) || (gItemAgeReqs[itemIndex] == AGE_REQ_NONE) || (gItemAgeReqs[itemIndex] == gSaveContext.linkAge)) void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx); @@ -53,7 +45,6 @@ void KaleidoScope_ProcessPlayerPreRender(); void KaleidoScope_SetupPlayerPreRender(PlayState* play); void KaleidoScope_DrawCursor(PlayState* play, u16 pageIndex); void KaleidoScope_UpdateDungeonMap(PlayState* play); -void KaleidoScope_SetArrowSelectActive(PauseContext* pauseCtx, bool active); void PauseMapMark_Draw(PlayState* play); @@ -61,4 +52,22 @@ void KaleidoScope_UpdateCursorSize(PauseContext* pauseCtx); void KaleidoScope_ResetTradeSelect(); +/* Alternate item menu */ +typedef enum { + SLOT_ALT_DINS_FIRE, SLOT_ALT_BOMB, SLOT_ALT_BOMBCHU, SLOT_ALT_NUT, SLOT_ALT_LENS, SLOT_ALT_BEAN, + SLOT_ALT_FARORES_WIND, SLOT_ALT_SLINGSHOT, SLOT_ALT_BOOMERANG, SLOT_ALT_STICK, SLOT_ALT_BOOTS_HOVER, SLOT_ALT_TRADE_CHILD, + SLOT_ALT_NAYRUS_LOVE, SLOT_ALT_BOW, SLOT_ALT_HOOKSHOT, SLOT_ALT_HAMMER, SLOT_ALT_BOOTS_IRON, SLOT_ALT_TRADE_ADULT, + SLOT_ALT_EMPTY_LEFT, SLOT_ALT_BOTTLE_1, SLOT_ALT_BOTTLE_2, SLOT_ALT_BOTTLE_3, SLOT_ALT_BOTTLE_4, SLOT_ALT_EMPTY_RIGHT, + SLOT_ALT_NONE = 0xFF +} InventorySlotAlt; + +extern u8 gSlotAgeReqsAlt[24]; +extern u8 gAltItemSlots[71]; +extern u8 gAltToMainSlot[24]; +#define _CHECK_AGE_REQ_SLOT_MAIN(slotIndex) (CVarGetInteger("gTimelessEquipment", 0) || (gSlotAgeReqs[slotIndex] == AGE_REQ_NONE) || gSlotAgeReqs[slotIndex] == ((void)0, gSaveContext.linkAge)) +#define _CHECK_AGE_REQ_SLOT_ALT(slotIndex) (CVarGetInteger("gTimelessEquipment", 0) || (gSlotAgeReqsAlt[slotIndex] == AGE_REQ_NONE) || gSlotAgeReqsAlt[slotIndex] == ((void)0, gSaveContext.linkAge)) +#define CHECK_AGE_REQ_SLOT(slotIndex) (CVarGetInteger("gAltItemMenu", 0) ? _CHECK_AGE_REQ_SLOT_ALT(slotIndex) : _CHECK_AGE_REQ_SLOT_MAIN(slotIndex)) +#define KALEIDO_SLOT(item) (CVarGetInteger("gAltItemMenu", 0) ? gAltItemSlots[item] : SLOT(item)) +u8 KaleidoScope_ItemInSlot(u8 slot); + #endif 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 8eb8c7375c7..c7529101dd1 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 @@ -734,30 +734,57 @@ static u16 D_8082ABEC[] = { }; u8 gSlotAgeReqs[] = { - AGE_REQ_NONE, // SLOT_DINS_FIRE + AGE_REQ_CHILD, // SLOT_DEKU_STICK + AGE_REQ_NONE, // SLOT_DEKU_NUT AGE_REQ_NONE, // SLOT_BOMB + AGE_REQ_ADULT, // SLOT_BOW + AGE_REQ_ADULT, // SLOT_ARROW_FIRE + AGE_REQ_NONE, // SLOT_DINS_FIRE + AGE_REQ_CHILD, // SLOT_SLINGSHOT + AGE_REQ_NONE, // SLOT_OCARINA AGE_REQ_NONE, // SLOT_BOMBCHU - AGE_REQ_NONE, // SLOT_NUT - AGE_REQ_NONE, // SLOT_LENS - AGE_REQ_CHILD, // SLOT_BEAN + AGE_REQ_ADULT, // SLOT_HOOKSHOT + AGE_REQ_ADULT, // SLOT_ARROW_ICE AGE_REQ_NONE, // SLOT_FARORES_WIND - AGE_REQ_CHILD, // SLOT_SLINGSHOT AGE_REQ_CHILD, // SLOT_BOOMERANG - AGE_REQ_CHILD, // SLOT_STICK - AGE_REQ_ADULT, // SLOT_BOOTS_HOVER - AGE_REQ_CHILD, // SLOT_TRADE_CHILD - AGE_REQ_NONE, // SLOT_NAYRUS_LOVE - AGE_REQ_ADULT, // SLOT_BOW - AGE_REQ_ADULT, // SLOT_HOOKSHOT + AGE_REQ_NONE, // SLOT_LENS_OF_TRUTH + AGE_REQ_CHILD, // SLOT_MAGIC_BEAN AGE_REQ_ADULT, // SLOT_HAMMER - AGE_REQ_ADULT, // SLOT_BOOTS_IRON - AGE_REQ_ADULT, // SLOT_TRADE_ADULT - AGE_REQ_NONE, // SLOT_EMPTY_LEFT + AGE_REQ_ADULT, // SLOT_ARROW_LIGHT + AGE_REQ_NONE, // SLOT_NAYRUS_LOVE AGE_REQ_NONE, // SLOT_BOTTLE_1 AGE_REQ_NONE, // SLOT_BOTTLE_2 AGE_REQ_NONE, // SLOT_BOTTLE_3 AGE_REQ_NONE, // SLOT_BOTTLE_4 - AGE_REQ_NONE, // SLOT_EMPTY_RIGHT + AGE_REQ_ADULT, // SLOT_TRADE_ADULT + AGE_REQ_CHILD, // SLOT_TRADE_CHILD +}; + +u8 gSlotAgeReqsAlt[] = { + AGE_REQ_NONE, // SLOT_ALT_DINS_FIRE + AGE_REQ_NONE, // SLOT_ALT_BOMB + AGE_REQ_NONE, // SLOT_ALT_BOMBCHU + AGE_REQ_NONE, // SLOT_ALT_NUT + AGE_REQ_NONE, // SLOT_ALT_LENS + AGE_REQ_CHILD, // SLOT_ALT_BEAN + AGE_REQ_NONE, // SLOT_ALT_FARORES_WIND + AGE_REQ_CHILD, // SLOT_ALT_SLINGSHOT + AGE_REQ_CHILD, // SLOT_ALT_BOOMERANG + AGE_REQ_CHILD, // SLOT_ALT_STICK + AGE_REQ_ADULT, // SLOT_ALT_BOOTS_HOVER + AGE_REQ_CHILD, // SLOT_ALT_TRADE_CHILD + AGE_REQ_NONE, // SLOT_ALT_NAYRUS_LOVE + AGE_REQ_ADULT, // SLOT_ALT_BOW + AGE_REQ_ADULT, // SLOT_ALT_HOOKSHOT + AGE_REQ_ADULT, // SLOT_ALT_HAMMER + AGE_REQ_ADULT, // SLOT_ALT_BOOTS_IRON + AGE_REQ_ADULT, // SLOT_ALT_TRADE_ADULT + AGE_REQ_NONE, // SLOT_ALT_EMPTY_LEFT + AGE_REQ_NONE, // SLOT_ALT_BOTTLE_1 + AGE_REQ_NONE, // SLOT_ALT_BOTTLE_2 + AGE_REQ_NONE, // SLOT_ALT_BOTTLE_3 + AGE_REQ_NONE, // SLOT_ALT_BOTTLE_4 + AGE_REQ_NONE, // SLOT_ALT_EMPTY_RIGHT }; u8 gEquipAgeReqs[][4] = { @@ -877,6 +904,38 @@ u8 gItemAgeReqs[] = { AGE_REQ_ADULT, // ITEM_GIANTS_KNIFE }; +u8 gMainToAltSlot[] = { + SLOT_ALT_STICK, SLOT_ALT_NUT, SLOT_ALT_BOMB, SLOT_ALT_BOW, SLOT_ALT_NONE, SLOT_ALT_DINS_FIRE, + SLOT_ALT_SLINGSHOT, SLOT_ALT_NONE, SLOT_ALT_BOMBCHU, SLOT_ALT_HOOKSHOT, SLOT_ALT_NONE, SLOT_ALT_FARORES_WIND, + SLOT_ALT_BOOMERANG, SLOT_ALT_LENS, SLOT_ALT_BEAN, SLOT_ALT_HAMMER, SLOT_ALT_NONE, SLOT_ALT_NAYRUS_LOVE, + SLOT_ALT_BOTTLE_1, SLOT_ALT_BOTTLE_2, SLOT_ALT_BOTTLE_3, SLOT_ALT_BOTTLE_4, SLOT_ALT_TRADE_ADULT, SLOT_ALT_TRADE_CHILD, +}; + +u8 gAltToMainSlot[] = { + SLOT_DINS_FIRE, SLOT_BOMB, SLOT_BOMBCHU, SLOT_NUT, SLOT_LENS, SLOT_BEAN, + SLOT_FARORES_WIND, SLOT_SLINGSHOT, SLOT_BOOMERANG, SLOT_STICK, SLOT_BOOTS_IRON, SLOT_TRADE_CHILD, + SLOT_NAYRUS_LOVE, SLOT_BOW, SLOT_HOOKSHOT, SLOT_HAMMER, SLOT_BOOTS_HOVER, SLOT_TRADE_ADULT, + SLOT_NONE, SLOT_BOTTLE_1, SLOT_BOTTLE_2, SLOT_BOTTLE_3, SLOT_BOTTLE_4, SLOT_NONE, +}; + +u8 gAltItemSlots[] = { + SLOT_ALT_STICK, SLOT_ALT_NUT, SLOT_ALT_BOMB, SLOT_ALT_BOW, SLOT_ALT_NONE, + SLOT_ALT_DINS_FIRE, SLOT_ALT_SLINGSHOT, SLOT_ALT_NONE, SLOT_ALT_NONE, SLOT_ALT_BOMBCHU, + SLOT_ALT_HOOKSHOT, SLOT_ALT_HOOKSHOT, SLOT_ALT_NONE, SLOT_ALT_FARORES_WIND, SLOT_ALT_BOOMERANG, + SLOT_ALT_LENS, SLOT_ALT_BEAN, SLOT_ALT_HAMMER, SLOT_ALT_NONE, SLOT_ALT_NAYRUS_LOVE, + SLOT_ALT_BOTTLE_1, SLOT_ALT_BOTTLE_1, SLOT_ALT_BOTTLE_1, SLOT_ALT_BOTTLE_1, SLOT_ALT_BOTTLE_1, + SLOT_ALT_BOTTLE_1, SLOT_ALT_BOTTLE_1, SLOT_ALT_BOTTLE_1, SLOT_ALT_BOTTLE_1, SLOT_ALT_BOTTLE_1, + SLOT_ALT_BOTTLE_1, SLOT_ALT_BOTTLE_1, SLOT_ALT_BOTTLE_1, SLOT_ALT_TRADE_CHILD, SLOT_ALT_TRADE_CHILD, + SLOT_ALT_TRADE_CHILD, SLOT_ALT_TRADE_CHILD, SLOT_ALT_TRADE_CHILD, SLOT_ALT_TRADE_CHILD, SLOT_ALT_TRADE_CHILD, + SLOT_ALT_TRADE_CHILD, SLOT_ALT_TRADE_CHILD, SLOT_ALT_TRADE_CHILD, SLOT_ALT_TRADE_CHILD, SLOT_ALT_TRADE_CHILD, + SLOT_ALT_TRADE_ADULT, SLOT_ALT_TRADE_ADULT, SLOT_ALT_TRADE_ADULT, SLOT_ALT_TRADE_ADULT, SLOT_ALT_TRADE_ADULT, + SLOT_ALT_TRADE_ADULT, SLOT_ALT_TRADE_ADULT, SLOT_ALT_TRADE_ADULT, SLOT_ALT_TRADE_ADULT, SLOT_ALT_TRADE_ADULT, + SLOT_ALT_TRADE_ADULT, SLOT_ALT_BOW, SLOT_ALT_BOW, SLOT_ALT_BOW, SLOT_ALT_NONE, + SLOT_ALT_NONE, SLOT_ALT_NONE, SLOT_ALT_NONE, SLOT_ALT_NONE, SLOT_ALT_NONE, + SLOT_ALT_NONE, SLOT_ALT_NONE, SLOT_ALT_NONE, SLOT_ALT_NONE, SLOT_ALT_BOOTS_IRON, + SLOT_ALT_BOOTS_HOVER, +}; + u8 gAreaGsFlags[] = { 0x0F, 0x1F, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x07, 0x07, 0x03, 0x0F, 0x07, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0x1F, 0x0F, 0x03, 0x0F, @@ -1009,15 +1068,15 @@ void KaleidoScope_SetDefaultCursor(PlayState* play) { s16 s; s16 i; gSelectingMask = false; - KaleidoScope_SetArrowSelectActive(pauseCtx, false); + gSelectingArrow = false; switch (pauseCtx->pageIndex) { case PAUSE_ITEM: s = pauseCtx->cursorSlot[PAUSE_ITEM]; - if (gSaveContext.inventory.items[s] == ITEM_NONE) { + if (KaleidoScope_ItemInSlot(s) == ITEM_NONE) { i = s + 1; while (true) { - if (gSaveContext.inventory.items[i] != ITEM_NONE) { + if (KaleidoScope_ItemInSlot(i) != ITEM_NONE) { break; } i++; @@ -1029,7 +1088,7 @@ void KaleidoScope_SetDefaultCursor(PlayState* play) { return; } } - pauseCtx->cursorItem[PAUSE_ITEM] = gSaveContext.inventory.items[i]; + pauseCtx->cursorItem[PAUSE_ITEM] = KaleidoScope_ItemInSlot(i); pauseCtx->cursorSlot[PAUSE_ITEM] = i; } break; @@ -1044,7 +1103,7 @@ void KaleidoScope_SwitchPage(PauseContext* pauseCtx, u8 pt) { pauseCtx->unk_1E4 = 1; pauseCtx->unk_1EA = 0; gSelectingMask = false; - KaleidoScope_SetArrowSelectActive(pauseCtx, false); + gSelectingArrow = false; if (!pt) { pauseCtx->mode = pauseCtx->pageIndex * 2 + 1; @@ -2073,7 +2132,7 @@ void KaleidoScope_DrawInfoPanel(PlayState* play) { bool pauseAnyCursor = (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); - if (!pauseCtx->pageIndex && (!pauseAnyCursor || (gSaveContext.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] != ITEM_NONE))) { // pageIndex == PAUSE_ITEM + if (!pauseCtx->pageIndex && (!pauseAnyCursor || (KaleidoScope_ItemInSlot(pauseCtx->cursorPoint[PAUSE_ITEM]) != ITEM_NONE))) { // pageIndex == PAUSE_ITEM pauseCtx->infoPanelVtx[16].v.ob[0] = pauseCtx->infoPanelVtx[18].v.ob[0] = WREG(49 + gSaveContext.language); @@ -2222,7 +2281,7 @@ void KaleidoScope_UpdateNamePanel(PlayState* play) { if (pauseAnyCursor && ((pauseCtx->pageIndex == PAUSE_EQUIP && pauseCtx->cursorX[PAUSE_EQUIP] != 0 && !CHECK_OWNED_EQUIP(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP] - 1)) || - (pauseCtx->pageIndex == PAUSE_ITEM && gSaveContext.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]] == ITEM_NONE))) { + (pauseCtx->pageIndex == PAUSE_ITEM && KaleidoScope_ItemInSlot(pauseCtx->cursorPoint[PAUSE_ITEM]) == ITEM_NONE))) { pauseCtx->namedItem = PAUSE_ITEM_NONE; } @@ -2642,7 +2701,8 @@ s16 func_80823A0C(PlayState* play, Vtx* vtx, s16 arg2, s16 arg3) { } /* Maps an ammo item to an inventory slot by 4x its slot number */ -static s16 sAmmoVtxTableIdx[] = { 4, 8, 12, 20, 28, 36, 52 }; +static s16 sAmmoVtxTableIdx[] = { 0, 4, 8, 12, 24, 32, 56 }; +static s16 sAmmoVtxTableIdxAlt[] = { 36, 12, 4, 52, 28, 8, 20 }; static s16 D_8082B12C[] = { -114, 12, 44, 76 }; @@ -2807,8 +2867,12 @@ void KaleidoScope_InitVertices(PlayState* play, GraphicsContext* gfxCtx) { for (phi_t3 = 1; phi_t3 < ARRAY_COUNT(gSaveContext.equips.buttonItems); phi_t3++, phi_t2 += 4) { if (gSaveContext.equips.cButtonSlots[phi_t3 - 1] != ITEM_NONE && - ((phi_t3 < 5) || CVarGetInteger("gDpadEquips", 0))) { - phi_t4 = gSaveContext.equips.cButtonSlots[phi_t3 - 1] * 4; + ((phi_t3 < 4) || CVarGetInteger("gDpadEquips", 0))) { + int slot = gSaveContext.equips.cButtonSlots[phi_t3 - 1]; + if (CVarGetInteger("gAltItemMenu", 0)) { + slot = gMainToAltSlot[slot]; + } + phi_t4 = slot * 4; pauseCtx->itemVtx[phi_t2 + 0].v.ob[0] = pauseCtx->itemVtx[phi_t2 + 2].v.ob[0] = pauseCtx->itemVtx[phi_t4].v.ob[0] - 2; @@ -2857,7 +2921,11 @@ void KaleidoScope_InitVertices(PlayState* play, GraphicsContext* gfxCtx) { } for (phi_t3 = 0; phi_t3 < 7; phi_t3++) { - phi_t4 = sAmmoVtxTableIdx[phi_t3]; + if (CVarGetInteger("gAltItemMenu", 0)) { + phi_t4 = sAmmoVtxTableIdxAlt[phi_t3]; + } else { + phi_t4 = sAmmoVtxTableIdx[phi_t3]; + } pauseCtx->itemVtx[phi_t2 + 0].v.ob[0] = pauseCtx->itemVtx[phi_t2 + 2].v.ob[0] = pauseCtx->itemVtx[phi_t4].v.ob[0]; @@ -2918,7 +2986,7 @@ void KaleidoScope_InitVertices(PlayState* play, GraphicsContext* gfxCtx) { pauseCtx->equipVtx[phi_t4 + 0].v.ob[0] + 28; pauseCtx->equipVtx[phi_t4 + 0].v.ob[1] = pauseCtx->equipVtx[phi_t4 + 1].v.ob[1] = - phi_t5 + pauseCtx->offsetY - 2 - (phi_t3 > 0 ? 16 : 0); + phi_t5 + pauseCtx->offsetY - 2 - ((CVarGetInteger("gAltItemMenu", 0) && phi_t3 > 0) ? 16 : 0); pauseCtx->equipVtx[phi_t4 + 2].v.ob[1] = pauseCtx->equipVtx[phi_t4 + 3].v.ob[1] = pauseCtx->equipVtx[phi_t4 + 0].v.ob[1] - 28; @@ -3109,34 +3177,6 @@ void KaleidoScope_InitVertices(PlayState* play, GraphicsContext* gfxCtx) { pauseCtx->saveVtx = Graph_Alloc(gfxCtx, 80 * sizeof(Vtx)); func_80823A0C(play, pauseCtx->saveVtx, 5, 5); - - pauseCtx->arrowSelectVtx = Graph_Alloc(gfxCtx, 32 * sizeof(Vtx)); - - // All arrow select vertices - for (phi_t2 = 0; phi_t2 < 32; phi_t2++) { - pauseCtx->arrowSelectVtx[phi_t2].v.flag = 0; - - // Z position - pauseCtx->arrowSelectVtx[phi_t2].v.ob[2] = 0; - - // Color - pauseCtx->arrowSelectVtx[phi_t2].v.cn[0] = pauseCtx->arrowSelectVtx[phi_t2].v.cn[1] = - pauseCtx->arrowSelectVtx[phi_t2].v.cn[2] = pauseCtx->arrowSelectVtx[phi_t2].v.cn[3] = 255; - } - - // All arrow select quads - for (phi_t2 = 0; phi_t2 < 32; phi_t2 += 4) { - // Top left UV at (0, 0); - pauseCtx->arrowSelectVtx[phi_t2 + 0].v.tc[0] = pauseCtx->arrowSelectVtx[phi_t2 + 0].v.tc[1] = - pauseCtx->arrowSelectVtx[phi_t2 + 1].v.tc[1] = pauseCtx->arrowSelectVtx[phi_t2 + 2].v.tc[0] = 0; - } - - // Background quads - for (phi_t2 = 16; phi_t2 < 32; phi_t2 += 4) { - // Bottom left UV at (32, 32) - pauseCtx->arrowSelectVtx[phi_t2 + 1].v.tc[0] = pauseCtx->arrowSelectVtx[phi_t2 + 2].v.tc[1] = - pauseCtx->arrowSelectVtx[phi_t2 + 3].v.tc[0] = pauseCtx->arrowSelectVtx[phi_t2 + 3].v.tc[1] = 0x400; - } } void KaleidoScope_DrawGameOver(PlayState* play) { @@ -4539,9 +4579,6 @@ void KaleidoScope_Update(PlayState* play) break; case 0x12: - // OTRTODO: move this somewhere it won't be called repeatedly for several frames - KaleidoScope_SetArrowSelectActive(pauseCtx, false); - if (pauseCtx->unk_1F4 != 160.0f) { pauseCtx->unk_1F4 = pauseCtx->unk_1F8 = pauseCtx->unk_1FC = pauseCtx->unk_200 += 160.0f / WREG(6); pauseCtx->infoPanelOffsetY -= 40 / WREG(6);