item tracker

This commit is contained in:
Demur Rumed 2025-08-02 13:59:48 +00:00
commit 72e3e71938
4 changed files with 109 additions and 7 deletions

View file

@ -1,4 +1,5 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/randomizer/context.h"
#include "soh/ShipInit.hpp" #include "soh/ShipInit.hpp"
extern "C" { extern "C" {

View file

@ -120,6 +120,12 @@ std::vector<ItemTrackerItem> bossSoulItems = {
ITEM_TRACKER_ITEM(RG_GANON_SOUL, 0, DrawItem), ITEM_TRACKER_ITEM(RG_GANON_SOUL, 0, DrawItem),
}; };
std::vector<ItemTrackerItem> jabbernutItems = {
ITEM_TRACKER_ITEM(RG_SPEAK_DEKU, 0, DrawItem), ITEM_TRACKER_ITEM(RG_SPEAK_GERUDO, 0, DrawItem),
ITEM_TRACKER_ITEM(RG_SPEAK_GORON, 0, DrawItem), ITEM_TRACKER_ITEM(RG_SPEAK_HYLIAN, 0, DrawItem),
ITEM_TRACKER_ITEM(RG_SPEAK_KOKIRI, 0, DrawItem), ITEM_TRACKER_ITEM(RG_SPEAK_ZORA, 0, DrawItem),
};
std::vector<ItemTrackerItem> ocarinaButtonItems = { std::vector<ItemTrackerItem> ocarinaButtonItems = {
// Hack for right now, just gonna draw ocarina buttons as ocarinas. // Hack for right now, just gonna draw ocarina buttons as ocarinas.
// Will replace with other macro once we have a custom texture // Will replace with other macro once we have a custom texture
@ -228,6 +234,11 @@ std::map<uint16_t, std::string> itemTrackerBossShortNames = {
{ RG_BONGO_BONGO_SOUL, "BONGO" }, { RG_TWINROVA_SOUL, "TWIN" }, { RG_GANON_SOUL, "GANON" }, { RG_BONGO_BONGO_SOUL, "BONGO" }, { RG_TWINROVA_SOUL, "TWIN" }, { RG_GANON_SOUL, "GANON" },
}; };
std::map<uint16_t, std::string> itemTrackerJabbernutShortNames = {
{ RG_SPEAK_DEKU, "DEKU" }, { RG_SPEAK_GERUDO, "GERUDO" }, { RG_SPEAK_GORON, "GORON" },
{ RG_SPEAK_HYLIAN, "HYLIAN" }, { RG_SPEAK_KOKIRI, "KOKIRI" }, { RG_SPEAK_ZORA, "ZORA" },
};
std::map<uint16_t, std::string> itemTrackerOcarinaButtonShortNames = { std::map<uint16_t, std::string> itemTrackerOcarinaButtonShortNames = {
{ RG_OCARINA_A_BUTTON, "A" }, { RG_OCARINA_C_UP_BUTTON, "C-U" }, { RG_OCARINA_C_DOWN_BUTTON, "C-D" }, { RG_OCARINA_A_BUTTON, "A" }, { RG_OCARINA_C_UP_BUTTON, "C-U" }, { RG_OCARINA_C_DOWN_BUTTON, "C-D" },
{ RG_OCARINA_C_LEFT_BUTTON, "C-L" }, { RG_OCARINA_C_RIGHT_BUTTON, "C-R" }, { RG_OCARINA_C_LEFT_BUTTON, "C-L" }, { RG_OCARINA_C_RIGHT_BUTTON, "C-R" },
@ -812,6 +823,42 @@ void DrawItem(ItemTrackerItem item) {
itemName = "Ganon's Soul"; itemName = "Ganon's Soul";
break; break;
case RG_SPEAK_DEKU:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_DEKU);
itemName = "Deku Jabbernut";
break;
case RG_SPEAK_GERUDO:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_GERUDO);
itemName = "Gerudo Jabbernut";
break;
case RG_SPEAK_GORON:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_GORON);
itemName = "Goron Jabbernut";
break;
case RG_SPEAK_HYLIAN:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_HYLIAN);
itemName = "Hylian Jabbernut";
break;
case RG_SPEAK_KOKIRI:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_KOKIRI);
itemName = "Kokiri Jabbernut";
break;
case RG_SPEAK_ZORA:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_ZORA);
itemName = "Zora Jabbernut";
break;
case RG_OCARINA_A_BUTTON: case RG_OCARINA_A_BUTTON:
actualItemId = item.id; actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A); hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A);
@ -989,6 +1036,16 @@ void DrawItem(ItemTrackerItem item) {
ImGui::PopStyleColor(); ImGui::PopStyleColor();
} }
if (item.id >= RG_SPEAK_DEKU && item.id <= RG_SPEAK_ZORA) {
ImVec2 p = ImGui::GetCursorScreenPos();
std::string name = itemTrackerJabbernutShortNames[item.id];
ImGui::SetCursorScreenPos(
ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(name.c_str()).x / 2), p.y - (iconSize + 13)));
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL_WHITE);
ImGui::Text("%s", name.c_str());
ImGui::PopStyleColor();
}
if (item.id >= RG_OCARINA_A_BUTTON && item.id <= RG_OCARINA_C_RIGHT_BUTTON) { if (item.id >= RG_OCARINA_A_BUTTON && item.id <= RG_OCARINA_C_RIGHT_BUTTON) {
ImVec2 p = ImGui::GetCursorScreenPos(); ImVec2 p = ImGui::GetCursorScreenPos();
std::string ocarinaButtonName = itemTrackerOcarinaButtonShortNames[item.id]; std::string ocarinaButtonName = itemTrackerOcarinaButtonShortNames[item.id];
@ -1435,8 +1492,8 @@ void UpdateVectors() {
// If we're adding boss souls to the main window... // If we're adding boss souls to the main window...
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.BossSouls"), SECTION_DISPLAY_HIDDEN) == if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.BossSouls"), SECTION_DISPLAY_HIDDEN) ==
SECTION_DISPLAY_MAIN_WINDOW) { SECTION_DISPLAY_MAIN_WINDOW) {
//...add empty items on the main window to get the souls on their own row. (Too many to sit with Greg/Triforce //...add empty items on the main window to get the souls on their own row
// pieces) // (Too many to sit with Greg/Triforce pieces)
while (mainWindowItems.size() % 6) { while (mainWindowItems.size() % 6) {
mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem));
} }
@ -1445,11 +1502,23 @@ void UpdateVectors() {
mainWindowItems.insert(mainWindowItems.end(), bossSoulItems.begin(), bossSoulItems.end()); mainWindowItems.insert(mainWindowItems.end(), bossSoulItems.begin(), bossSoulItems.end());
} }
// If we're adding jabbernuts to the main window...
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Jabbernuts"), SECTION_DISPLAY_HIDDEN) ==
SECTION_DISPLAY_MAIN_WINDOW) {
// there are 6 jabbernuts, perfect for a row
while (mainWindowItems.size() % 6) {
mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem));
}
// Add jabbernuts
mainWindowItems.insert(mainWindowItems.end(), jabbernutItems.begin(), jabbernutItems.end());
}
// If we're adding ocarina buttons to the main window... // If we're adding ocarina buttons to the main window...
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), SECTION_DISPLAY_HIDDEN) == if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), SECTION_DISPLAY_HIDDEN) ==
SECTION_DISPLAY_MAIN_WINDOW) { SECTION_DISPLAY_MAIN_WINDOW) {
//...add empty items on the main window to get the buttons on their own row. (Too many to sit with Greg/Triforce //...add empty items on the main window to get the buttons on their own row.
// pieces/boss souls) // (Too many to sit with Greg/Triforce pieces/boss souls)
while (mainWindowItems.size() % 6) { while (mainWindowItems.size() % 6) {
mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem));
} }
@ -1461,8 +1530,8 @@ void UpdateVectors() {
// If we're adding overworld keys to the main window... // If we're adding overworld keys to the main window...
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.OverworldKeys"), SECTION_DISPLAY_HIDDEN) == if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.OverworldKeys"), SECTION_DISPLAY_HIDDEN) ==
SECTION_DISPLAY_MAIN_WINDOW) { SECTION_DISPLAY_MAIN_WINDOW) {
//...add empty items on the main window to get the keys on their own row. (Too many to sit with Greg/Triforce //...add empty items on the main window to get the keys on their own row.
// pieces/boss souls/ocarina buttons) // (Too many to sit with Greg/Triforce pieces/boss souls/ocarina buttons)
while (mainWindowItems.size() % 6) { while (mainWindowItems.size() % 6) {
mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem));
} }
@ -1638,6 +1707,13 @@ void ItemTrackerWindow::DrawElement() {
EndFloatingWindows(); EndFloatingWindows();
} }
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Jabbernuts"), SECTION_DISPLAY_HIDDEN) ==
SECTION_DISPLAY_SEPARATE) {
BeginFloatingWindows("Jabbernut Tracker");
DrawItemsInRows(jabbernutItems);
EndFloatingWindows();
}
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), SECTION_DISPLAY_HIDDEN) == if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), SECTION_DISPLAY_HIDDEN) ==
SECTION_DISPLAY_SEPARATE) { SECTION_DISPLAY_SEPARATE) {
BeginFloatingWindows("Ocarina Button Tracker"); BeginFloatingWindows("Ocarina Button Tracker");
@ -1933,6 +2009,15 @@ void ItemTrackerSettingsWindow::DrawElement() {
shouldUpdateVectors = true; shouldUpdateVectors = true;
} }
if (CVarCombobox("Jabbernuts", CVAR_TRACKER_ITEM("DisplayType.Jabbernuts"), displayTypes,
ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_HIDDEN)
.ComponentAlignment(ComponentAlignments::Right)
.LabelPosition(LabelPositions::Far)
.Color(THEME_COLOR))) {
shouldUpdateVectors = true;
}
if (CVarCombobox("Ocarina Buttons", CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), displayTypes, if (CVarCombobox("Ocarina Buttons", CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), displayTypes,
ComboboxOptions() ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_HIDDEN) .DefaultIndex(SECTION_DISPLAY_HIDDEN)

View file

@ -212,7 +212,7 @@ void Settings::CreateOptions() {
OPT_BOOL(RSK_SHUFFLE_OCARINA, "Shuffle Ocarinas", CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), mOptionDescriptions[RSK_SHUFFLE_OCARINA]); OPT_BOOL(RSK_SHUFFLE_OCARINA, "Shuffle Ocarinas", CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), mOptionDescriptions[RSK_SHUFFLE_OCARINA]);
OPT_BOOL(RSK_SHUFFLE_OCARINA_BUTTONS, "Shuffle Ocarina Buttons", CVAR_RANDOMIZER_SETTING("ShuffleOcarinaButtons"), mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS]); OPT_BOOL(RSK_SHUFFLE_OCARINA_BUTTONS, "Shuffle Ocarina Buttons", CVAR_RANDOMIZER_SETTING("ShuffleOcarinaButtons"), mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS]);
OPT_BOOL(RSK_SHUFFLE_SWIM, "Shuffle Swim", CVAR_RANDOMIZER_SETTING("ShuffleSwim"), mOptionDescriptions[RSK_SHUFFLE_SWIM]); OPT_BOOL(RSK_SHUFFLE_SWIM, "Shuffle Swim", CVAR_RANDOMIZER_SETTING("ShuffleSwim"), mOptionDescriptions[RSK_SHUFFLE_SWIM]);
OPT_BOOL(RSK_SHUFFLE_SPEAK, "Shuffle Speak", CVAR_RANDOMIZER_SETTING("ShuffleSpeak"), mOptionDescriptions[RSK_SHUFFLE_SPEAK]); OPT_BOOL(RSK_SHUFFLE_SPEAK, "Shuffle Jabbernuts", CVAR_RANDOMIZER_SETTING("ShuffleSpeak"), mOptionDescriptions[RSK_SHUFFLE_SPEAK]);
OPT_BOOL(RSK_SHUFFLE_WEIRD_EGG, "Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]); OPT_BOOL(RSK_SHUFFLE_WEIRD_EGG, "Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]);
OPT_BOOL(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, "Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]); OPT_BOOL(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, "Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]);
OPT_U8(RSK_SHUFFLE_POTS, "Shuffle Pots", {"Off", "Dungeons", "Overworld", "All Pots"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShufflePots"), mOptionDescriptions[RSK_SHUFFLE_POTS], WidgetType::Combobox, RO_SHUFFLE_POTS_OFF); OPT_U8(RSK_SHUFFLE_POTS, "Shuffle Pots", {"Off", "Dungeons", "Overworld", "All Pots"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShufflePots"), mOptionDescriptions[RSK_SHUFFLE_POTS], WidgetType::Combobox, RO_SHUFFLE_POTS_OFF);

View file

@ -151,6 +151,15 @@ std::map<uint32_t, ItemMapEntry> bossSoulMapping = {
{ RG_GANON_SOUL, { RG_GANON_SOUL, "RG_GANON_SOUL", "RG_GANON_SOUL_Faded", gBossSoulTex } }, { RG_GANON_SOUL, { RG_GANON_SOUL, "RG_GANON_SOUL", "RG_GANON_SOUL_Faded", gBossSoulTex } },
}; };
std::map<uint32_t, ItemMapEntry> jabbernutMapping = {
{ RG_SPEAK_DEKU, { RG_SPEAK_DEKU, "RG_SPEAK_DEKU", "RG_SPEAK_DEKU_Faded", (char*)gItemIcons[ITEM_NUT] } },
{ RG_SPEAK_GERUDO, { RG_SPEAK_GERUDO, "RG_SPEAK_GERUDO", "RG_SPEAK_GERUDO_Faded", (char*)gItemIcons[ITEM_NUT] } },
{ RG_SPEAK_GORON, { RG_SPEAK_GORON, "RG_SPEAK_GORON", "RG_SPEAK_GORON_Faded", (char*)gItemIcons[ITEM_NUT] } },
{ RG_SPEAK_HYLIAN, { RG_SPEAK_HYLIAN, "RG_SPEAK_HYLIAN", "RG_SPEAK_HYLIAN_Faded", (char*)gItemIcons[ITEM_NUT] } },
{ RG_SPEAK_KOKIRI, { RG_SPEAK_KOKIRI, "RG_SPEAK_KOKIRI", "RG_SPEAK_KOKIRI_Faded", (char*)gItemIcons[ITEM_NUT] } },
{ RG_SPEAK_ZORA, { RG_SPEAK_ZORA, "RG_SPEAK_ZORA", "RG_SPEAK_ZORA_Faded", (char*)gItemIcons[ITEM_NUT] } },
};
std::map<uint32_t, QuestMapEntry> questMapping = { std::map<uint32_t, QuestMapEntry> questMapping = {
QUEST_MAP_ENTRY(QUEST_MEDALLION_FOREST, dgQuestIconMedallionForestTex), QUEST_MAP_ENTRY(QUEST_MEDALLION_FOREST, dgQuestIconMedallionForestTex),
QUEST_MAP_ENTRY(QUEST_MEDALLION_FIRE, dgQuestIconMedallionFireTex), QUEST_MAP_ENTRY(QUEST_MEDALLION_FIRE, dgQuestIconMedallionFireTex),
@ -230,6 +239,13 @@ void RegisterImGuiItemIcons() {
entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f)); entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f));
} }
for (const auto& entry : jabbernutMapping) {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath,
ImVec4(1, 1, 1, 1));
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(
entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f));
}
for (const auto& entry : questMapping) { for (const auto& entry : questMapping) {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath, Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath,
ImVec4(1, 1, 1, 1)); ImVec4(1, 1, 1, 1));