From 78790fe8aab4f33673a13e875a90240f9060248f Mon Sep 17 00:00:00 2001 From: Adam Bird Date: Sun, 13 Aug 2023 11:41:04 -0400 Subject: [PATCH] [Accessibility] Tweak Pause menu TTS functions (#3098) * tweak kaleido tts * tts announce what items are assigned to buttons; announce page on open --- .../accessibility/texts/kaleidoscope_eng.json | 39 ++-- .../accessibility/texts/kaleidoscope_fra.json | 39 ++-- .../accessibility/texts/kaleidoscope_ger.json | 39 ++-- .../assets/accessibility/texts/misc_eng.json | 10 +- .../assets/accessibility/texts/misc_fra.json | 10 +- .../assets/accessibility/texts/misc_ger.json | 10 +- soh/soh/Enhancements/tts/tts.cpp | 219 +++++++++++++++--- 7 files changed, 291 insertions(+), 75 deletions(-) diff --git a/OTRExporter/assets/accessibility/texts/kaleidoscope_eng.json b/OTRExporter/assets/accessibility/texts/kaleidoscope_eng.json index c1c472591..10b016b32 100644 --- a/OTRExporter/assets/accessibility/texts/kaleidoscope_eng.json +++ b/OTRExporter/assets/accessibility/texts/kaleidoscope_eng.json @@ -1,24 +1,35 @@ { - "health": "health $0", - "magic": "magic $0", - "rupees": "rupees $0", - "0": "Deku Stick $0", - "1": "Deku Nut $0", - "2": "Bomb $0", - "3": "Fairy Bow $0", + "health": "Health - $0 Hearts", + "magic": "Magic - $0", + "rupees": "Rupees - $0", + "floor": "Floor $0", + "basement": "Basement $0", + "item_menu": "Select Item", + "map_menu": "Map - $0", + "quest_menu": "Quest Status", + "equip_menu": "Equipment", + "overworld": "Overworld", + "equipped": "$0 - Equipped", + "save_prompt": "Would you like to save?", + "game_saved": "Game saved", + "assigned_to": "Assigned to $0", + "0": "Deku Stick - $0", + "1": "Deku Nut - $0", + "2": "Bomb - $0", + "3": "Fairy Bow - $0", "4": "Fire Arrow", "5": "Din's Fire", - "6": "Fairy Slingshot $0", + "6": "Fairy Slingshot - $0", "7": "Fairy Ocarina", "8": "Ocarina of Time", - "9": "Bombchu $0", + "9": "Bombchu - $0", "10": "Hookshot", "11": "Longshot", "12": "Ice Arrow", "13": "Farore's Wind", "14": "Boomerang", "15": "Lens of Truth", - "16": "Magic Beans $0", + "16": "Magic Beans - $0", "17": "Megaton Hammer", "18": "Light Arrow", "19": "Nayru's Love", @@ -115,8 +126,8 @@ "110": "Zora Sapphire", "111": "Stone of Agony", "112": "Gerudo's Card", - "113": "Skulltula Token $0", - "114": "Heart Container $0", + "113": "Skulltula Token - $0", + "114": "Piece of Heart - $0", "115": "Piece of Heart", "116": "Boss Key", "117": "Compass", @@ -124,7 +135,7 @@ "119": "Small Key", "120": "MAGIC SMALL", "121": "MAGIC LARGE", - "122": "PIECE OF HEART 2", + "122": "Biggoron's Sword", "123": "INVALID 1", "124": "INVALID 2", "125": "INVALID 3", @@ -217,4 +228,4 @@ "311": "Lon Lon Ranch", "312": "Question Mark", "313": "Ganon's Castle" -} \ No newline at end of file +} diff --git a/OTRExporter/assets/accessibility/texts/kaleidoscope_fra.json b/OTRExporter/assets/accessibility/texts/kaleidoscope_fra.json index 58898d70d..820eb4cbc 100644 --- a/OTRExporter/assets/accessibility/texts/kaleidoscope_fra.json +++ b/OTRExporter/assets/accessibility/texts/kaleidoscope_fra.json @@ -1,24 +1,35 @@ { - "health": "vie $0", - "magic": "magie $0", - "rupees": "rubis $0", - "0": "Bâton Mojo $0", - "1": "Noix Mojo $0", - "2": "Bombes $0", - "3": "Arc des Fées $0", + "health": "Vie - $0 Coeurs", + "magic": "Magie - $0", + "rupees": "Rubis - $0", + "floor": "Étage $0", + "basement": "Sous-sol $0", + "item_menu": "Inventaire", + "map_menu": "Carte - $0", + "quest_menu": "Statut de la quête", + "equip_menu": "Equipment", + "overworld": "Surmonde", + "equipped": "$0 - Équipé", + "save_prompt": "Voulez-vous sauvegarder?", + "game_saved": "Jeu sauvegardé", + "assigned_to": "Assigné au $0", + "0": "Bâton Mojo - $0", + "1": "Noix Mojo - $0", + "2": "Bombes - $0", + "3": "Arc des Fées - $0", "4": "Flèche de Feu", "5": "Feu de Din", - "6": "Lance-Pierre des Fées $0", + "6": "Lance-Pierre des Fées - $0", "7": "Ocarina des Fées", "8": "Ocarina of Temps", - "9": "Missiles Teigneux $0", + "9": "Missiles Teigneux - $0", "10": "Grappin", "11": "Super Grappin", "12": "Flèche de Glace", "13": "Vent de Farore", "14": "Boomerang", "15": "Monocle de Vérité", - "16": "Haricot Magique $0", + "16": "Haricot Magique - $0", "17": "Masse des Titans", "18": "Flèche de Lumière", "19": "Amour de Nayru", @@ -115,8 +126,8 @@ "110": "Saphir Zora", "111": "Pierre de Souffrance", "112": "Carte Gerudo", - "113": "Skulltula d'or $0", - "114": "Coeur d'Énergie $0", + "113": "Skulltula d'or - $0", + "114": "Quart de Coeur - $0", "115": "Quart de Coeur", "116": "Clé d'or", "117": "Boussole", @@ -124,7 +135,7 @@ "119": "Petite Clé", "120": "PETITE BOUTEILLE DE MAGIE", "121": "GRANDE BOUTEILLE DE MAGIE", - "122": "QUART DE COEUR 2", + "122": "Épée de Biggoron", "123": "INVALIDE 1", "124": "INVALIDE 2", "125": "INVALIDE 3", @@ -217,4 +228,4 @@ "311": "Ranch Lon Lon", "312": "Point d'interrogation", "313": "Château de Ganon" -} \ No newline at end of file +} diff --git a/OTRExporter/assets/accessibility/texts/kaleidoscope_ger.json b/OTRExporter/assets/accessibility/texts/kaleidoscope_ger.json index 460b32877..630d933fc 100644 --- a/OTRExporter/assets/accessibility/texts/kaleidoscope_ger.json +++ b/OTRExporter/assets/accessibility/texts/kaleidoscope_ger.json @@ -1,24 +1,35 @@ { - "health": "Energie $0", - "magic": "Magie $0", - "rupees": "Rubine $0", - "0": "Deku-Stab $0", - "1": "Deku-Nuß $0", - "2": "Bombe $0", - "3": "Feen-Bogen $0", + "health": "Energie - $0 Herzen", + "magic": "Magie - $0", + "rupees": "Rubine - $0", + "floor": "Etage $0", + "basement": "Keller $0", + "item_menu": "Gegenstände", + "map_menu": "Karte - $0", + "quest_menu": "Quest Status", + "equip_menu": "Ausrüstung", + "overworld": "Überwelt", + "equipped": "$0 - Ausgerüstet", + "save_prompt": "Spielstand sichern?", + "game_saved": "Spielstand gesichert", + "assigned_to": "$0 zugeordnet", + "0": "Deku-Stab - $0", + "1": "Deku-Nuß - $0", + "2": "Bombe - $0", + "3": "Feen-Bogen - $0", "4": "Feuer-Pfeil", "5": "Dins Feuerinferno", - "6": "Feen-Schleuder $0", + "6": "Feen-Schleuder - $0", "7": "Feen-Okarina", "8": "Okarina der Zeit", - "9": "Krabbelmine $0", + "9": "Krabbelmine - $0", "10": "Fanghaken", "11": "Enterhaken", "12": "Eis-Pfeil", "13": "Farores Donnersturm", "14": "Bumerang", "15": "Auge der Wahrheit", - "16": "Wundererbsen $0", + "16": "Wundererbsen - $0", "17": "Stahlhammer", "18": "Licht-Pfeil", "19": "Nayrus Umarmung", @@ -115,8 +126,8 @@ "110": "Zora-Saphir", "111": "Stein des Wissens", "112": "Gerudo-Paß", - "113": "Skulltula-Symbol $0", - "114": "Herzcontainer $0", + "113": "Skulltula-Symbol - $0", + "114": "Herzteil - $0", "115": "Herzteil", "116": "Master-Schlüssel", "117": "Kompaß", @@ -124,7 +135,7 @@ "119": "Kleiner Schlüssel", "120": "MAGIE KLEIN", "121": "MAGIE GROß", - "122": "HERZTEIL 2", + "122": "Biggoron-Schwert", "123": "UNGÜLTIG 1", "124": "UNGÜLTIG 2", "125": "UNGÜLTIG 3", @@ -217,4 +228,4 @@ "311": "Lon Lon-Farm", "312": "Fragezeichen", "313": "Teufelsturm" -} \ No newline at end of file +} diff --git a/OTRExporter/assets/accessibility/texts/misc_eng.json b/OTRExporter/assets/accessibility/texts/misc_eng.json index db59f3deb..6bff3b328 100644 --- a/OTRExporter/assets/accessibility/texts/misc_eng.json +++ b/OTRExporter/assets/accessibility/texts/misc_eng.json @@ -14,5 +14,11 @@ "input_button_c_left": "C Left", "input_button_c_right": "C Right", "input_analog_stick": "the Analog Stick", - "input_d_pad": "the D-Pad" -} \ No newline at end of file + "input_d_pad": "the D-Pad", + "input_d_pad_up": "D-Pad Up", + "input_d_pad_down": "D-Pad Down", + "input_d_pad_left": "D-Pad Left", + "input_d_pad_right": "D-Pad Right", + "yes": "Yes", + "no": "No" +} diff --git a/OTRExporter/assets/accessibility/texts/misc_fra.json b/OTRExporter/assets/accessibility/texts/misc_fra.json index e37268b95..0d9073e50 100644 --- a/OTRExporter/assets/accessibility/texts/misc_fra.json +++ b/OTRExporter/assets/accessibility/texts/misc_fra.json @@ -14,5 +14,11 @@ "input_button_c_left": "C Gauche", "input_button_c_right": "C Droit", "input_analog_stick": "le Stick Analogique", - "input_d_pad": "D-Pad" -} \ No newline at end of file + "input_d_pad": "D-Pad", + "input_d_pad_up": "D-Pad Haut", + "input_d_pad_down": "D-Pad Bas", + "input_d_pad_left": "D-Pad Gauche", + "input_d_pad_right": "D-Pad Droit", + "yes": "Oui", + "no": "Non" +} diff --git a/OTRExporter/assets/accessibility/texts/misc_ger.json b/OTRExporter/assets/accessibility/texts/misc_ger.json index 23b887861..2e07143f0 100644 --- a/OTRExporter/assets/accessibility/texts/misc_ger.json +++ b/OTRExporter/assets/accessibility/texts/misc_ger.json @@ -14,5 +14,11 @@ "input_button_c_left": "C Links", "input_button_c_right": "C Rechts", "input_analog_stick": "den Analog-Stick", - "input_d_pad": "das Steuerkreuz" -} \ No newline at end of file + "input_d_pad": "das Steuerkreuz", + "input_d_pad_up": "Steuerkreuz Oben", + "input_d_pad_down": "Steuerkreuz Unten", + "input_d_pad_left": "Steuerkreuz Links", + "input_d_pad_right": "Steuerkreuz Rechts", + "yes": "Ja", + "no": "Nein" +} diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index fceb9c84a..5a646e3a9 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -12,6 +12,7 @@ #include "soh/Enhancements/boss-rush/BossRush.h" extern "C" { +extern MapData* gMapData; extern SaveContext gSaveContext; extern PlayState* gPlayState; } @@ -190,28 +191,109 @@ void RegisterOnInterfaceUpdateHook() { void RegisterOnKaleidoscopeUpdateHook() { GameInteractor::Instance->RegisterGameHook([](int16_t inDungeonScene) { if (!CVarGetInteger("gA11yTTS", 0)) return; - - static uint16_t prevCursorIndex = 0; + + static int16_t prevCursorIndex = 0; static uint16_t prevCursorSpecialPos = 0; static uint16_t prevCursorPoint[5] = { 0 }; - + static int16_t prevPromptChoice = -1; + static int16_t prevSubState = -1; + static int16_t prevState = -1; + PauseContext* pauseCtx = &gPlayState->pauseCtx; Input* input = &gPlayState->state.input[0]; - - if (pauseCtx->state != 6) { - //reset cursor index to so it is announced when pause is reopened - prevCursorIndex = -1; + + // Save game prompt + if (pauseCtx->state == 7) { + if (pauseCtx->unk_1EC == 1) { + // prompt + if (prevPromptChoice != pauseCtx->promptChoice) { + auto prompt = GetParameritizedText(pauseCtx->promptChoice == 0 ? "yes" : "no", TEXT_BANK_MISC, nullptr); + if (prevPromptChoice == -1) { + auto translation = GetParameritizedText("save_prompt", TEXT_BANK_KALEIDO, nullptr); + SpeechSynthesizer::Instance->Speak((translation + " - " + prompt).c_str(), GetLanguageCode()); + } else { + SpeechSynthesizer::Instance->Speak(prompt.c_str(), GetLanguageCode()); + } + + prevPromptChoice = pauseCtx->promptChoice; + } + } else if (pauseCtx->unk_1EC == 4 && prevSubState != 4) { + // Saved + auto translation = GetParameritizedText("game_saved", TEXT_BANK_KALEIDO, nullptr); + SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + } + prevSubState = pauseCtx->unk_1EC; + prevState = pauseCtx->state; return; } - + + // Announce page when + // Kaleido pages are rotating and page halfway rotated + // Or Kaleido was just opened + if ((pauseCtx->unk_1E4 == 1 && pauseCtx->unk_1EA == 32) || (pauseCtx->state == 4 && prevState != 4)) { + uint16_t modeNextPageMap[] = { + PAUSE_MAP, PAUSE_EQUIP, PAUSE_QUEST, PAUSE_ITEM, PAUSE_EQUIP, PAUSE_MAP, PAUSE_ITEM, PAUSE_QUEST, + }; + uint16_t nextPage = modeNextPageMap[pauseCtx->mode]; + + switch (nextPage) { + case PAUSE_ITEM: { + auto translation = GetParameritizedText("item_menu", TEXT_BANK_KALEIDO, nullptr); + SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + break; + } + case PAUSE_MAP: { + std::string map; + if (inDungeonScene) { + std::string key = std::to_string(gSaveContext.mapIndex); + map = GetParameritizedText(key, TEXT_BANK_SCENES, nullptr); + } else { + map = GetParameritizedText("overworld", TEXT_BANK_KALEIDO, nullptr); + } + auto translation = GetParameritizedText("map_menu", TEXT_BANK_KALEIDO, map.c_str()); + SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + break; + } + case PAUSE_QUEST: { + auto translation = GetParameritizedText("quest_menu", TEXT_BANK_KALEIDO, nullptr); + SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + break; + } + case PAUSE_EQUIP: { + auto translation = GetParameritizedText("equip_menu", TEXT_BANK_KALEIDO, nullptr); + SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + break; + } + } + prevState = pauseCtx->state; + return; + } + + prevState = pauseCtx->state; + + if (pauseCtx->state != 6) { + // Reset cursor index and values so it is announced when pause is reopened + prevCursorIndex = -1; + prevPromptChoice = -1; + prevSubState = -1; + return; + } + if ((pauseCtx->debugState != 1) && (pauseCtx->debugState != 2)) { char arg[8]; if (CHECK_BTN_ALL(input->press.button, BTN_DUP)) { - snprintf(arg, sizeof(arg), "%d", gSaveContext.health); + // Normalize hearts to fractional count similar to z_lifemeter + int curHeartFraction = gSaveContext.health % 16; + int fullHearts = gSaveContext.health / 16; + float fraction = ceilf((float)curHeartFraction / 5) * 0.25; + float health = (float)fullHearts + fraction; + snprintf(arg, sizeof(arg), "%g", health); auto translation = GetParameritizedText("health", TEXT_BANK_KALEIDO, arg); SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); - } else if (CHECK_BTN_ALL(input->press.button, BTN_DLEFT)) { - snprintf(arg, sizeof(arg), "%d", gSaveContext.magic); + } else if (CHECK_BTN_ALL(input->press.button, BTN_DLEFT) && gSaveContext.magicCapacity != 0) { + // Normalize magic to percentage + float magicLevel = ((float)gSaveContext.magic / gSaveContext.magicCapacity) * 100; + snprintf(arg, sizeof(arg), "%.0f%%", magicLevel); auto translation = GetParameritizedText("magic", TEXT_BANK_KALEIDO, arg); SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); } else if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { @@ -235,6 +317,17 @@ void RegisterOnKaleidoscopeUpdateHook() { if (pauseCtx->cursorSpecialPos > 0) { return; } + + std::string buttonNames[] = { + "input_button_c_left", + "input_button_c_down", + "input_button_c_right", + "input_d_pad_up", + "input_d_pad_down", + "input_d_pad_left", + "input_d_pad_right", + }; + int8_t assignedTo = -1; switch (pauseCtx->pageIndex) { case PAUSE_ITEM: @@ -247,36 +340,71 @@ void RegisterOnKaleidoscopeUpdateHook() { case ITEM_BOMBCHU: case ITEM_SLINGSHOT: case ITEM_BOW: - snprintf(arg, sizeof(arg), "%d", AMMO(pauseCtx->cursorItem[PAUSE_ITEM])); - break; case ITEM_BEAN: - snprintf(arg, sizeof(arg), "%d", 0); + snprintf(arg, sizeof(arg), "%d", AMMO(pauseCtx->cursorItem[PAUSE_ITEM])); break; default: arg[0] = '\0'; } - - if (pauseCtx->cursorItem[PAUSE_ITEM] == 999) { + + if (pauseCtx->cursorItem[PAUSE_ITEM] == PAUSE_ITEM_NONE || + pauseCtx->cursorItem[PAUSE_ITEM] == ITEM_NONE) { + prevCursorIndex = -1; return; } - + std::string key = std::to_string(pauseCtx->cursorItem[PAUSE_ITEM]); - auto translation = GetParameritizedText(key, TEXT_BANK_KALEIDO, arg); - SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + std::string itemTranslation = GetParameritizedText(key, TEXT_BANK_KALEIDO, arg); + + // Check if item is assigned to a button + for (size_t i = 0; i < ARRAY_COUNT(gSaveContext.equips.cButtonSlots); i++) { + if (gSaveContext.equips.buttonItems[i + 1] == pauseCtx->cursorItem[PAUSE_ITEM]) { + assignedTo = i; + break; + } + } + + if (assignedTo != -1) { + auto button = GetParameritizedText(buttonNames[assignedTo], TEXT_BANK_MISC, nullptr); + auto translation = GetParameritizedText("assigned_to", TEXT_BANK_KALEIDO, button.c_str()); + SpeechSynthesizer::Instance->Speak((itemTranslation + " - " + translation).c_str(), GetLanguageCode()); + } else { + SpeechSynthesizer::Instance->Speak(itemTranslation.c_str(), GetLanguageCode()); + } break; } case PAUSE_MAP: if (inDungeonScene) { + // Dungeon map items if (pauseCtx->cursorItem[PAUSE_MAP] != PAUSE_ITEM_NONE) { std::string key = std::to_string(pauseCtx->cursorItem[PAUSE_MAP]); auto translation = GetParameritizedText(key, TEXT_BANK_KALEIDO, nullptr); SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + } else { + // Dungeon map floor numbers + char arg[8]; + int cursorPoint = pauseCtx->cursorPoint[PAUSE_MAP]; + + // Cursor is on a dungeon floor position + if (cursorPoint >= 3 && cursorPoint < 11) { + int floorID = gMapData->floorID[gPlayState->interfaceCtx.unk_25A][pauseCtx->dungeonMapSlot - 3]; + // Normalize so F1 == 0, and negative numbers are basement levels + int normalizedFloor = (floorID * -1) + 8; + if (normalizedFloor >= 0) { + snprintf(arg, sizeof(arg), "%d", normalizedFloor + 1); + auto translation = GetParameritizedText("floor", TEXT_BANK_KALEIDO, arg); + SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + } else { + snprintf(arg, sizeof(arg), "%d", normalizedFloor * -1); + auto translation = GetParameritizedText("basement", TEXT_BANK_KALEIDO, arg); + SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + } + } } } else { std::string key = std::to_string(0x0100 + pauseCtx->cursorPoint[PAUSE_WORLD_MAP]); auto translation = GetParameritizedText(key, TEXT_BANK_KALEIDO, nullptr); SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); - SPDLOG_INFO("Item: {}", key); } break; case PAUSE_QUEST: @@ -287,16 +415,17 @@ void RegisterOnKaleidoscopeUpdateHook() { snprintf(arg, sizeof(arg), "%d", gSaveContext.inventory.gsTokens); break; case ITEM_HEART_CONTAINER: - snprintf(arg, sizeof(arg), "%d", ((gSaveContext.inventory.questItems & 0xF) & 0xF) >> 0x1C); + snprintf(arg, sizeof(arg), "%d", (gSaveContext.inventory.questItems & 0xF0000000) >> 0x1C); break; default: arg[0] = '\0'; } - - if (pauseCtx->cursorItem[PAUSE_QUEST] == 999) { + + if (pauseCtx->cursorItem[PAUSE_QUEST] == PAUSE_ITEM_NONE) { + prevCursorIndex = -1; return; } - + std::string key = std::to_string(pauseCtx->cursorItem[PAUSE_QUEST]); auto translation = GetParameritizedText(key, TEXT_BANK_KALEIDO, arg); SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); @@ -304,15 +433,51 @@ void RegisterOnKaleidoscopeUpdateHook() { } case PAUSE_EQUIP: { + if (pauseCtx->namedItem == PAUSE_ITEM_NONE) { + prevCursorIndex = -1; + return; + } + std::string key = std::to_string(pauseCtx->cursorItem[PAUSE_EQUIP]); - auto translation = GetParameritizedText(key, TEXT_BANK_KALEIDO, nullptr); - SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + auto itemTranslation = GetParameritizedText(key, TEXT_BANK_KALEIDO, nullptr); + uint8_t checkEquipItem = pauseCtx->namedItem; + + // BGS from kaleido reports as ITEM_HEART_PIECE_2 (122) + // remap BGS and broken knife to be the BGS item for the current equip check + if (checkEquipItem == ITEM_HEART_PIECE_2 || checkEquipItem == ITEM_SWORD_KNIFE) { + checkEquipItem = ITEM_SWORD_BGS; + } + + // Check if equipment item is currently equipped or assigned to a button + if (checkEquipItem >= ITEM_SWORD_KOKIRI && checkEquipItem <= ITEM_BOOTS_HOVER) { + uint8_t checkEquipType = (checkEquipItem - ITEM_SWORD_KOKIRI) / 3; + uint8_t checkEquipValue = ((checkEquipItem - ITEM_SWORD_KOKIRI) % 3) + 1; + + if (CUR_EQUIP_VALUE(checkEquipType) == checkEquipValue) { + itemTranslation = GetParameritizedText("equipped", TEXT_BANK_KALEIDO, itemTranslation.c_str()); + } + + for (size_t i = 0; i < ARRAY_COUNT(gSaveContext.equips.cButtonSlots); i++) { + if (gSaveContext.equips.buttonItems[i + 1] == checkEquipItem) { + assignedTo = i; + break; + } + } + } + + if (assignedTo != -1) { + auto button = GetParameritizedText(buttonNames[assignedTo], TEXT_BANK_MISC, nullptr); + auto translation = GetParameritizedText("assigned_to", TEXT_BANK_KALEIDO, button.c_str()); + SpeechSynthesizer::Instance->Speak((itemTranslation + " - " + translation).c_str(), GetLanguageCode()); + } else { + SpeechSynthesizer::Instance->Speak(itemTranslation.c_str(), GetLanguageCode()); + } break; } default: break; } - + prevCursorIndex = cursorIndex; memcpy(prevCursorPoint, pauseCtx->cursorPoint, sizeof(prevCursorPoint)); });