mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-08-21 13:53:49 -07:00
[Accessibility] Tweak Pause menu TTS functions (#3098)
* tweak kaleido tts * tts announce what items are assigned to buttons; announce page on open
This commit is contained in:
parent
05dde45a75
commit
78790fe8aa
7 changed files with 291 additions and 75 deletions
|
@ -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<GameInteractor::OnKaleidoscopeUpdate>([](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));
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue