diff --git a/modules/boot/include/menus/menu.h b/modules/boot/include/menus/menu.h index dfc37bcc..43455b90 100644 --- a/modules/boot/include/menus/menu.h +++ b/modules/boot/include/menus/menu.h @@ -45,6 +45,10 @@ enum MenuIndex { MN_ITEM_WHELL_INDEX, MN_PAUSE_INDEX, MN_AMOUNTS_INDEX, + // Pause menu's sub menus + MN_EQUIPMENT_INDEX, + MN_GOLDEN_BUGS_INDEX, + MN_HIDDEN_SKILLS_INDEX, // Memory menu's sub menus MN_WATCHES_INDEX, MN_MEMORY_EDITOR_INDEX, @@ -71,8 +75,7 @@ enum MenuIndex { // Tools menu's sub menus MN_CHECKERS_INDEX, - // Pause menu's sub menus - MN_GOLDEN_BUGS_INDEX, + // This entry is used only to get a count of the number of valid entries. MN_COUNT diff --git a/modules/boot/src/menus/menu.cpp b/modules/boot/src/menus/menu.cpp index e8d0d90f..a4528d3d 100644 --- a/modules/boot/src/menus/menu.cpp +++ b/modules/boot/src/menus/menu.cpp @@ -9,14 +9,15 @@ const char* g_menuPaths[MN_COUNT] = { "warp", "general_flags", "dungeon_flags", "portal_flags", "rupee_flags", "flag_records", "flag_log", "item_wheel", "pause", - "amounts", + "amounts", "equipment", "golden_bugs", + "hidden_skills", "watches", "memory_editor", "memfiles", "any_saves", "any_bite_saves", "hundo_saves", "ad_saves", "nosq_saves", "glitchless_saves", "actor_spawn", "actor_list", "collision_view", "projection_view", "trigger_view", "sound_test", "pos_settings", "credits", "combo", - "checkers", "golden_bugs" + "checkers", }; KEEP_FUNC Menu::Menu(Cursor& cursor) : cursor(cursor) {} \ No newline at end of file diff --git a/modules/menus/menu_equipment/CMakeLists.txt b/modules/menus/menu_equipment/CMakeLists.txt new file mode 100644 index 00000000..24e35f3c --- /dev/null +++ b/modules/menus/menu_equipment/CMakeLists.txt @@ -0,0 +1,5 @@ +file(GLOB_RECURSE srcs CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") +file(GLOB_RECURSE asms CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.s") +list(APPEND srcs ${asms}) +get_filename_component(rel_name ${CMAKE_CURRENT_SOURCE_DIR} NAME) +tpgz_add_module(${rel_name} "${srcs}" "${CMAKE_CURRENT_SOURCE_DIR}/include") \ No newline at end of file diff --git a/modules/menus/menu_equipment/include/equipment_menu.h b/modules/menus/menu_equipment/include/equipment_menu.h new file mode 100644 index 00000000..44172cde --- /dev/null +++ b/modules/menus/menu_equipment/include/equipment_menu.h @@ -0,0 +1,45 @@ +#include "menus/menu.h" + +struct EquipmentData { + uint8_t l_ordonSword_idx; + uint8_t l_masterSword_idx; + uint8_t l_woodShield_idx; + uint8_t l_hyShield_idx; + uint8_t l_tunic_idx; + uint8_t l_zoraArmor_idx; + uint8_t l_magicArmor_idx; + uint8_t l_bombCap_idx; + uint8_t l_wallet_idx; + uint8_t l_arrowCap_idx; +}; + +enum EquipmentIndex { + ORDON_SWORD_INDEX, + MASTER_SWORD_INDEX, + WOOD_SHIELD_INDEX, + HYLIAN_SHIELD_INDEX, + HERO_TUNIC_INDEX, + ZORA_ARMOR_INDEX, + MAGIC_ARMOR_INDEX, + BOMB_CAPACITY_INDEX, + WALLET_INDEX, + ARROW_CAPACITY_INDEX, + + EQUIPMENT_INDEX_COUNT +}; + +extern EquipmentData* equipmentData; + +class EquipmentMenu : public Menu { +public: + EquipmentMenu(Cursor&); + virtual ~EquipmentMenu(); + virtual void draw(); + +private: + Line lines[EQUIPMENT_INDEX_COUNT]; + + void resetIndex(); + void getEquipment(); + void setEquipment(); +}; \ No newline at end of file diff --git a/modules/menus/menu_equipment/include/main.h b/modules/menus/menu_equipment/include/main.h new file mode 100644 index 00000000..1935f7ae --- /dev/null +++ b/modules/menus/menu_equipment/include/main.h @@ -0,0 +1,6 @@ +#pragma once + +namespace tpgz::modules { +void main(); +void exit(); +} // namespace tpgz::modules \ No newline at end of file diff --git a/modules/menus/menu_equipment/src/equipment_menu.cpp b/modules/menus/menu_equipment/src/equipment_menu.cpp new file mode 100644 index 00000000..f4c33d99 --- /dev/null +++ b/modules/menus/menu_equipment/src/equipment_menu.cpp @@ -0,0 +1,351 @@ +#include "menus/menu_equipment/include/equipment_menu.h" +#include +#include "libtp_c/include/d/com/d_com_inf_game.h" +#include "libtp_c/include/utils.h" +#include "gz_flags.h" +#include "rels/include/defines.h" +#include "menus/utils/menu_mgr.h" + +#define MAX_ORDON_SWORD_OPT 3 +#define MAX_MASTER_SWORD_OPT 3 +#define MAX_WOOD_SHIELD_OPT 3 +#define MAX_HYLIAN_SHIELD_OPT 2 +#define MAX_HERO_TUNIC_OPT 2 +#define MAX_ZORA_ARMOR_OPT 2 +#define MAX_MAGIC_ARMOR_OPT 2 +#define MAX_BOMB_CAPACITY_OPT 2 +#define MAX_WALLET_OPT 3 +#define MAX_ARROW_CAPACITY_OPT 3 + +KEEP_VAR EquipmentData* equipmentData; + +KEEP_FUNC EquipmentMenu::EquipmentMenu(Cursor& cursor) + : Menu(cursor), + lines{{"ordon sword:", ORDON_SWORD_INDEX, "Wooden Sword / Ordon Sword", false, nullptr, + MAX_ORDON_SWORD_OPT}, + {"master sword:", MASTER_SWORD_INDEX, "Master Sword / Light Sword", false, nullptr, + MAX_MASTER_SWORD_OPT}, + {"wooden shield:", WOOD_SHIELD_INDEX, "Ordon Shield / Wooden Shield", false, nullptr, + MAX_WOOD_SHIELD_OPT}, + {"hylian shield:", HYLIAN_SHIELD_INDEX, "Hylian Shield", false, nullptr, + MAX_HYLIAN_SHIELD_OPT}, + {"hero's tunic:", HERO_TUNIC_INDEX, "Hero's Tunic", false, nullptr, MAX_HERO_TUNIC_OPT}, + {"zora armor:", ZORA_ARMOR_INDEX, "Zora Armor", false, nullptr, MAX_ZORA_ARMOR_OPT}, + {"magic armor:", MAGIC_ARMOR_INDEX, "Magic Armor", false, nullptr, MAX_MAGIC_ARMOR_OPT}, + {"bomb capacity:", BOMB_CAPACITY_INDEX, "Bomb Bag Capacity", false, nullptr, + MAX_BOMB_CAPACITY_OPT}, + {"wallet upgrade:", WALLET_INDEX, "Wallet Capacity", false, nullptr, MAX_WALLET_OPT}, + {"arrow capacity:", ARROW_CAPACITY_INDEX, "Arrow Quiver Capacity", false, nullptr, + MAX_ARROW_CAPACITY_OPT}} {} + +EquipmentMenu::~EquipmentMenu() {} + +void EquipmentMenu::resetIndex() { + equipmentData->l_ordonSword_idx = 0; + equipmentData->l_masterSword_idx = 0; + equipmentData->l_woodShield_idx = 0; + equipmentData->l_hyShield_idx = 0; + equipmentData->l_tunic_idx = 0; + equipmentData->l_zoraArmor_idx = 0; + equipmentData->l_magicArmor_idx = 0; + equipmentData->l_bombCap_idx = 0; + equipmentData->l_wallet_idx = 0; + equipmentData->l_arrowCap_idx = 0; +} + +void EquipmentMenu::getEquipment() { + if (dComIfGs_isItemFirstBit(SWORD)) { + equipmentData->l_ordonSword_idx = 2; + } else if (dComIfGs_isItemFirstBit(WOOD_STICK)) { + equipmentData->l_ordonSword_idx = 1; + } + + if (dComIfGs_isItemFirstBit(LIGHT_SWORD)) { + equipmentData->l_masterSword_idx = 2; + } else if (dComIfGs_isItemFirstBit(MASTER_SWORD)) { + equipmentData->l_masterSword_idx = 1; + } + + if (dComIfGs_isItemFirstBit(SHIELD)) { + equipmentData->l_woodShield_idx = 2; + } else if (dComIfGs_isItemFirstBit(WOOD_SHIELD)) { + equipmentData->l_woodShield_idx = 1; + } + + if (dComIfGs_isItemFirstBit(HYLIA_SHIELD)) { + equipmentData->l_hyShield_idx = 1; + } + + if (dComIfGs_isItemFirstBit(WEAR_KOKIRI)) { + equipmentData->l_tunic_idx = 1; + } + + if (dComIfGs_isItemFirstBit(WEAR_ZORA)) { + equipmentData->l_zoraArmor_idx = 1; + } + + if (dComIfGs_isItemFirstBit(ARMOR)) { + equipmentData->l_magicArmor_idx = 1; + } + + if (dComIfGs_isItemFirstBit(BOMB_BAG_LV2)) { + equipmentData->l_bombCap_idx = 1; + } + + switch (dComIfGs_getWalletSize()) { + case 1: + equipmentData->l_wallet_idx = 1; + break; + case 2: + equipmentData->l_wallet_idx = 2; + break; + } + + if (dComIfGs_getArrowMax() == 100) { + equipmentData->l_arrowCap_idx = 2; + } else if (dComIfGs_getArrowMax() == 60) { + equipmentData->l_arrowCap_idx = 1; + } +} + +void EquipmentMenu::setEquipment() { + switch (equipmentData->l_ordonSword_idx) { + case 0: + dComIfGs_offItemFirstBit(WOOD_STICK); + dComIfGs_offItemFirstBit(SWORD); + break; + case 1: + dComIfGs_onItemFirstBit(WOOD_STICK); + dComIfGs_offItemFirstBit(SWORD); + break; + case 2: + dComIfGs_onItemFirstBit(SWORD); + dComIfGs_offItemFirstBit(WOOD_STICK); + break; + } + + switch (equipmentData->l_masterSword_idx) { + case 0: + dComIfGs_offItemFirstBit(MASTER_SWORD); + dComIfGs_offItemFirstBit(LIGHT_SWORD); + break; + case 1: + dComIfGs_onItemFirstBit(MASTER_SWORD); + dComIfGs_offItemFirstBit(LIGHT_SWORD); + break; + case 2: + dComIfGs_onItemFirstBit(LIGHT_SWORD); + break; + } + + switch (equipmentData->l_woodShield_idx) { + case 0: + dComIfGs_offItemFirstBit(SHIELD); + dComIfGs_offItemFirstBit(WOOD_SHIELD); + break; + case 1: + dComIfGs_onItemFirstBit(WOOD_SHIELD); + break; + case 2: + dComIfGs_onItemFirstBit(SHIELD); + break; + } + + switch (equipmentData->l_hyShield_idx) { + case 0: + dComIfGs_offItemFirstBit(HYLIA_SHIELD); + break; + case 1: + dComIfGs_onItemFirstBit(HYLIA_SHIELD); + break; + } + + switch (equipmentData->l_tunic_idx) { + case 0: + dComIfGs_offItemFirstBit(WEAR_KOKIRI); + break; + case 1: + dComIfGs_onItemFirstBit(WEAR_KOKIRI); + break; + } + + switch (equipmentData->l_zoraArmor_idx) { + case 0: + dComIfGs_offItemFirstBit(WEAR_ZORA); + break; + case 1: + dComIfGs_onItemFirstBit(WEAR_ZORA); + break; + } + + switch (equipmentData->l_magicArmor_idx) { + case 0: + dComIfGs_offItemFirstBit(ARMOR); + break; + case 1: + dComIfGs_onItemFirstBit(ARMOR); + break; + } + + switch (equipmentData->l_bombCap_idx) { + case 0: + dComIfGs_offItemFirstBit(BOMB_BAG_LV2); + break; + case 1: + dComIfGs_onItemFirstBit(BOMB_BAG_LV2); + break; + } + + switch (equipmentData->l_wallet_idx) { + case 0: + dComIfGs_setWalletSize(WALLET); + break; + case 1: + dComIfGs_setWalletSize(BIG_WALLET); + break; + case 2: + dComIfGs_setWalletSize(GIANT_WALLET); + break; + } + + switch (equipmentData->l_arrowCap_idx) { + case 0: + dComIfGs_setArrowMax(30); + break; + case 1: + dComIfGs_setArrowMax(60); + break; + case 2: + dComIfGs_setArrowMax(100); + break; + } +} + +void EquipmentMenu::draw() { + static bool init = false; + cursor.setMode(Cursor::MODE_LIST); + + if (!init) { + getEquipment(); + init = true; + } + + if (GZ_getButtonTrig(BACK_BUTTON)) { + init = false; + g_menuMgr->pop(); + resetIndex(); + return; + } + + ListMember ordonSword_opt[3] = {"none", "wooden sword", "ordon sword"}; + ListMember masterSword_opt[3] = {"none", "master sword", "light sword"}; + ListMember woodShield_opt[3] = {"none", "ordon shield", "wooden shield"}; + ListMember hyShield_opt[2] = {"none", "hylian shield"}; + ListMember tunic_opt[2] = {"none", "hero's tunic"}; + ListMember zoraArmor_opt[2] = {"none", "zora armor"}; + ListMember magicArmor_opt[2] = {"none", "magic armor"}; + ListMember bombCap_opt[2] = {"30/15/10", "60/30/20"}; + ListMember wallet_opt[3] = {"300 Rupees", "600 Rupees", "1000 Rupees"}; + ListMember arrowCap_opt[3] = {"30 Arrows", "60 Arrows", "100 Arrows"}; + + switch (cursor.y) { + case ORDON_SWORD_INDEX: + cursor.x = equipmentData->l_ordonSword_idx; + cursor.move(MAX_ORDON_SWORD_OPT, MENU_LINE_NUM); + + if (cursor.y == ORDON_SWORD_INDEX) { + equipmentData->l_ordonSword_idx = cursor.x; + } + break; + case MASTER_SWORD_INDEX: + cursor.x = equipmentData->l_masterSword_idx; + cursor.move(MAX_MASTER_SWORD_OPT, MENU_LINE_NUM); + + if (cursor.y == MASTER_SWORD_INDEX) { + equipmentData->l_masterSword_idx = cursor.x; + } + break; + case WOOD_SHIELD_INDEX: + cursor.x = equipmentData->l_woodShield_idx; + cursor.move(MAX_WOOD_SHIELD_OPT, MENU_LINE_NUM); + + if (cursor.y == WOOD_SHIELD_INDEX) { + equipmentData->l_woodShield_idx = cursor.x; + } + break; + case HYLIAN_SHIELD_INDEX: + cursor.x = equipmentData->l_hyShield_idx; + cursor.move(MAX_HYLIAN_SHIELD_OPT, MENU_LINE_NUM); + + if (cursor.y == HYLIAN_SHIELD_INDEX) { + equipmentData->l_hyShield_idx = cursor.x; + } + break; + case HERO_TUNIC_INDEX: + cursor.x = equipmentData->l_tunic_idx; + cursor.move(MAX_HERO_TUNIC_OPT, MENU_LINE_NUM); + + if (cursor.y == HERO_TUNIC_INDEX) { + equipmentData->l_tunic_idx = cursor.x; + } + break; + case ZORA_ARMOR_INDEX: + cursor.x = equipmentData->l_zoraArmor_idx; + cursor.move(MAX_ZORA_ARMOR_OPT, MENU_LINE_NUM); + + if (cursor.y == ZORA_ARMOR_INDEX) { + equipmentData->l_zoraArmor_idx = cursor.x; + } + break; + case MAGIC_ARMOR_INDEX: + cursor.x = equipmentData->l_magicArmor_idx; + cursor.move(MAX_MAGIC_ARMOR_OPT, MENU_LINE_NUM); + + if (cursor.y == MAGIC_ARMOR_INDEX) { + equipmentData->l_magicArmor_idx = cursor.x; + } + break; + case BOMB_CAPACITY_INDEX: + cursor.x = equipmentData->l_bombCap_idx; + cursor.move(MAX_BOMB_CAPACITY_OPT, MENU_LINE_NUM); + + if (cursor.y == BOMB_CAPACITY_INDEX) { + equipmentData->l_bombCap_idx = cursor.x; + } + break; + case WALLET_INDEX: + cursor.x = equipmentData->l_wallet_idx; + cursor.move(MAX_WALLET_OPT, MENU_LINE_NUM); + + if (cursor.y == WALLET_INDEX) { + equipmentData->l_wallet_idx = cursor.x; + } + break; + case ARROW_CAPACITY_INDEX: + cursor.x = equipmentData->l_arrowCap_idx; + cursor.move(MAX_ARROW_CAPACITY_OPT, MENU_LINE_NUM); + + if (cursor.y == ARROW_CAPACITY_INDEX) { + equipmentData->l_arrowCap_idx = cursor.x; + } + break; + default: + cursor.move(0, MENU_LINE_NUM); + break; + } + + setEquipment(); + + lines[ORDON_SWORD_INDEX].printf(" <%s>", ordonSword_opt[equipmentData->l_ordonSword_idx].member); + lines[MASTER_SWORD_INDEX].printf(" <%s>", masterSword_opt[equipmentData->l_masterSword_idx].member); + lines[WOOD_SHIELD_INDEX].printf(" <%s>", woodShield_opt[equipmentData->l_woodShield_idx].member); + lines[HYLIAN_SHIELD_INDEX].printf(" <%s>", hyShield_opt[equipmentData->l_hyShield_idx].member); + lines[HERO_TUNIC_INDEX].printf(" <%s>", tunic_opt[equipmentData->l_tunic_idx].member); + lines[ZORA_ARMOR_INDEX].printf(" <%s>", zoraArmor_opt[equipmentData->l_zoraArmor_idx].member); + lines[MAGIC_ARMOR_INDEX].printf(" <%s>", magicArmor_opt[equipmentData->l_magicArmor_idx].member); + lines[BOMB_CAPACITY_INDEX].printf(" <%s>", bombCap_opt[equipmentData->l_bombCap_idx].member); + lines[WALLET_INDEX].printf(" <%s>", wallet_opt[equipmentData->l_wallet_idx].member); + lines[ARROW_CAPACITY_INDEX].printf(" <%s>", arrowCap_opt[equipmentData->l_arrowCap_idx].member); + + GZ_drawMenuLines(lines, cursor.y, MENU_LINE_NUM); +} diff --git a/modules/menus/menu_equipment/src/main.cpp b/modules/menus/menu_equipment/src/main.cpp new file mode 100644 index 00000000..ed0a6b41 --- /dev/null +++ b/modules/menus/menu_equipment/src/main.cpp @@ -0,0 +1,56 @@ +#include +#include "menus/menu_equipment/include/equipment_menu.h" +#include "events/draw_listener.h" +#include "menus/utils/menu_mgr.h" +#include "utils/draw.h" + +void onCreate(); +void onLoad(); +void onDraw(); +void onUnload(); +void onDelete(); + +EquipmentMenu* l_menu; + +namespace tpgz::modules { +void main() { + g_menuMgr->setCreateHook(onCreate); + g_menuMgr->setLoadHook(onLoad); + g_menuMgr->setUnloadHook(onUnload); + g_menuMgr->setDeleteHook(onDelete); +} +void exit() { + g_menuMgr->setCreateHook(nullptr); + g_menuMgr->setLoadHook(nullptr); + g_menuMgr->setUnloadHook(nullptr); + g_menuMgr->setDeleteHook(nullptr); +} +} // namespace tpgz::modules + +void onCreate() { + g_menuMgr->setPersistentData(new EquipmentData); + if (!g_menuMgr->getPermanentData()) { + g_menuMgr->setPermanentData(new Cursor); + } +} + +void onLoad() { + equipmentData = g_menuMgr->getPersistentData(); + l_menu = new EquipmentMenu(*g_menuMgr->getPermanentData()); + g_drawListener->addListener(onDraw); +} + +void onDraw() { + l_menu->draw(); +} + +void onUnload() { + g_drawListener->removeListener(onDraw); + delete l_menu; +} + +void onDelete() { + auto data = g_menuMgr->getPersistentData(); + delete data; + g_menuMgr->setPersistentData(nullptr); +} diff --git a/modules/menus/menu_hidden_skills/CMakeLists.txt b/modules/menus/menu_hidden_skills/CMakeLists.txt new file mode 100644 index 00000000..24e35f3c --- /dev/null +++ b/modules/menus/menu_hidden_skills/CMakeLists.txt @@ -0,0 +1,5 @@ +file(GLOB_RECURSE srcs CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") +file(GLOB_RECURSE asms CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.s") +list(APPEND srcs ${asms}) +get_filename_component(rel_name ${CMAKE_CURRENT_SOURCE_DIR} NAME) +tpgz_add_module(${rel_name} "${srcs}" "${CMAKE_CURRENT_SOURCE_DIR}/include") \ No newline at end of file diff --git a/modules/menus/menu_hidden_skills/include/hidden_skills_menu.h b/modules/menus/menu_hidden_skills/include/hidden_skills_menu.h new file mode 100644 index 00000000..cdc5b3a8 --- /dev/null +++ b/modules/menus/menu_hidden_skills/include/hidden_skills_menu.h @@ -0,0 +1,35 @@ +#include "menus/menu.h" + +struct HiddenSkillsData { + bool l_ebFlag; + bool l_sbFlag; + bool l_bsFlag; + bool l_hsFlag; + bool l_mdFlag; + bool l_jsFlag; + bool l_gsFlag; +}; + +enum HiddenSkillsIndex { + ENDING_BLOW_INDEX, + SHIELD_BASH_INDEX, + BACKSLICE_INDEX, + HELM_SPLITTER_INDEX, + MORTAL_DRAW_INDEX, + JUMP_STRIKE_INDEX, + GREAT_SPIN_INDEX, + + HIDDEN_SKILLS_INDEX_COUNT +}; + +extern HiddenSkillsData* hiddenSkillsData; + +class HiddenSkillsMenu : public Menu { +public: + HiddenSkillsMenu(Cursor&); + virtual ~HiddenSkillsMenu(); + virtual void draw(); + +private: + Line lines[HIDDEN_SKILLS_INDEX_COUNT]; +}; \ No newline at end of file diff --git a/modules/menus/menu_hidden_skills/include/main.h b/modules/menus/menu_hidden_skills/include/main.h new file mode 100644 index 00000000..1935f7ae --- /dev/null +++ b/modules/menus/menu_hidden_skills/include/main.h @@ -0,0 +1,6 @@ +#pragma once + +namespace tpgz::modules { +void main(); +void exit(); +} // namespace tpgz::modules \ No newline at end of file diff --git a/modules/menus/menu_hidden_skills/src/hidden_skills_menu.cpp b/modules/menus/menu_hidden_skills/src/hidden_skills_menu.cpp new file mode 100644 index 00000000..fd4b75a6 --- /dev/null +++ b/modules/menus/menu_hidden_skills/src/hidden_skills_menu.cpp @@ -0,0 +1,68 @@ +#include "menus/menu_hidden_skills/include/hidden_skills_menu.h" +#include +#include "libtp_c/include/d/com/d_com_inf_game.h" +#include "libtp_c/include/utils.h" +#include "gz_flags.h" +#include "rels/include/defines.h" +#include "menus/utils/menu_mgr.h" + +KEEP_VAR HiddenSkillsData* hiddenSkillsData; + +KEEP_FUNC HiddenSkillsMenu::HiddenSkillsMenu(Cursor& cursor) + : Menu(cursor), + lines{{"ending blow:", ENDING_BLOW_INDEX, "Ending Blow", true, [](){return hiddenSkillsData->l_ebFlag;}}, + {"shield bash:", SHIELD_BASH_INDEX, "Shield Bash", true, [](){return hiddenSkillsData->l_sbFlag;}}, + {"backslice:", BACKSLICE_INDEX, "Backslice", true, [](){return hiddenSkillsData->l_bsFlag;}}, + {"helm splitter:", HELM_SPLITTER_INDEX, "Helm Splitter", true, [](){return hiddenSkillsData->l_hsFlag;}}, + {"mortal draw:", MORTAL_DRAW_INDEX, "Mortal Draw", true, [](){return hiddenSkillsData->l_mdFlag;}}, + {"jump strike:", JUMP_STRIKE_INDEX, "Jump Strike", true, [](){return hiddenSkillsData->l_jsFlag;}}, + {"greatspin:", GREAT_SPIN_INDEX, "Greatspin", true, [](){return hiddenSkillsData->l_gsFlag;}}} {} + +HiddenSkillsMenu::~HiddenSkillsMenu() {} + +void HiddenSkillsMenu::draw() { + cursor.setMode(Cursor::MODE_LIST); + + if (GZ_getButtonTrig(BACK_BUTTON)) { + g_menuMgr->pop(); + return; + } + + // update hidden skill flags + hiddenSkillsData->l_ebFlag = dComIfGs_isEventBit(0x2904); + hiddenSkillsData->l_sbFlag = dComIfGs_isEventBit(0x2908); + hiddenSkillsData->l_bsFlag = dComIfGs_isEventBit(0x2902); + hiddenSkillsData->l_hsFlag = dComIfGs_isEventBit(0x2901); + hiddenSkillsData->l_mdFlag = dComIfGs_isEventBit(0x2A80); + hiddenSkillsData->l_jsFlag = dComIfGs_isEventBit(0x2A40); + hiddenSkillsData->l_gsFlag = dComIfGs_isEventBit(0x2A20); + + if (GZ_getButtonTrig(SELECTION_BUTTON)) { + switch (cursor.y) { + case ENDING_BLOW_INDEX: + setEventFlag(0x2904); + break; + case SHIELD_BASH_INDEX: + setEventFlag(0x2908); + break; + case BACKSLICE_INDEX: + setEventFlag(0x2902); + break; + case HELM_SPLITTER_INDEX: + setEventFlag(0x2901); + break; + case MORTAL_DRAW_INDEX: + setEventFlag(0x2A80); + break; + case JUMP_STRIKE_INDEX: + setEventFlag(0x2A40); + break; + case GREAT_SPIN_INDEX: + setEventFlag(0x2A20); + break; + } + } + + cursor.move(0, MENU_LINE_NUM); + GZ_drawMenuLines(lines, cursor.y, MENU_LINE_NUM); +} diff --git a/modules/menus/menu_hidden_skills/src/main.cpp b/modules/menus/menu_hidden_skills/src/main.cpp new file mode 100644 index 00000000..aa517183 --- /dev/null +++ b/modules/menus/menu_hidden_skills/src/main.cpp @@ -0,0 +1,56 @@ +#include +#include "menus/menu_hidden_skills/include/hidden_skills_menu.h" +#include "events/draw_listener.h" +#include "menus/utils/menu_mgr.h" +#include "utils/draw.h" + +void onCreate(); +void onLoad(); +void onDraw(); +void onUnload(); +void onDelete(); + +HiddenSkillsMenu* l_menu; + +namespace tpgz::modules { +void main() { + g_menuMgr->setCreateHook(onCreate); + g_menuMgr->setLoadHook(onLoad); + g_menuMgr->setUnloadHook(onUnload); + g_menuMgr->setDeleteHook(onDelete); +} +void exit() { + g_menuMgr->setCreateHook(nullptr); + g_menuMgr->setLoadHook(nullptr); + g_menuMgr->setUnloadHook(nullptr); + g_menuMgr->setDeleteHook(nullptr); +} +} // namespace tpgz::modules + +void onCreate() { + g_menuMgr->setPersistentData(new HiddenSkillsData); + if (!g_menuMgr->getPermanentData()) { + g_menuMgr->setPermanentData(new Cursor); + } +} + +void onLoad() { + hiddenSkillsData = g_menuMgr->getPersistentData(); + l_menu = new HiddenSkillsMenu(*g_menuMgr->getPermanentData()); + g_drawListener->addListener(onDraw); +} + +void onDraw() { + l_menu->draw(); +} + +void onUnload() { + g_drawListener->removeListener(onDraw); + delete l_menu; +} + +void onDelete() { + auto data = g_menuMgr->getPersistentData(); + delete data; + g_menuMgr->setPersistentData(nullptr); +} diff --git a/modules/menus/menu_pause/include/pause_menu.h b/modules/menus/menu_pause/include/pause_menu.h index f19f4d69..403334b1 100644 --- a/modules/menus/menu_pause/include/pause_menu.h +++ b/modules/menus/menu_pause/include/pause_menu.h @@ -1,46 +1,14 @@ #include "menus/menu.h" struct PauseData { - uint8_t l_ordonSword_idx; - uint8_t l_masterSword_idx; - uint8_t l_woodShield_idx; - uint8_t l_hyShield_idx; - uint8_t l_tunic_idx; - uint8_t l_zoraArmor_idx; - uint8_t l_magicArmor_idx; - uint8_t l_bombCap_idx; - uint8_t l_wallet_idx; - uint8_t l_arrowCap_idx; uint8_t l_scent_idx; - bool l_ebFlag; - bool l_sbFlag; - bool l_bsFlag; - bool l_hsFlag; - bool l_mdFlag; - bool l_jsFlag; - bool l_gsFlag; }; enum PauseIndex { - ORDON_SWORD_INDEX, - MASTER_SWORD_INDEX, - WOOD_SHIELD_INDEX, - HYLIAN_SHIELD_INDEX, - HERO_TUNIC_INDEX, - ZORA_ARMOR_INDEX, - MAGIC_ARMOR_INDEX, - BOMB_CAPACITY_INDEX, - WALLET_INDEX, - ARROW_CAPACITY_INDEX, - SCENT_INDEX, + EQUIPMENT_INDEX, GOLDEN_BUG_INDEX, - ENDING_BLOW_INDEX, - SHIELD_BASH_INDEX, - BACKSLICE_INDEX, - HELM_SPLITTER_INDEX, - MORTAL_DRAW_INDEX, - JUMP_STRIKE_INDEX, - GREAT_SPIN_INDEX, + HIDDEN_SKILL_INDEX, + SCENT_INDEX, PAUSE_INDEX_COUNT }; @@ -55,8 +23,4 @@ class PauseMenu : public Menu { private: Line lines[PAUSE_INDEX_COUNT]; - - void resetIndex(); - void getEquipment(); - void setEquipment(); }; \ No newline at end of file diff --git a/modules/menus/menu_pause/src/pause_menu.cpp b/modules/menus/menu_pause/src/pause_menu.cpp index 2788fb67..78e2594b 100644 --- a/modules/menus/menu_pause/src/pause_menu.cpp +++ b/modules/menus/menu_pause/src/pause_menu.cpp @@ -6,118 +6,21 @@ #include "rels/include/defines.h" #include "menus/utils/menu_mgr.h" -#define MAX_ORDON_SWORD_OPT 3 -#define MAX_MASTER_SWORD_OPT 3 -#define MAX_WOOD_SHIELD_OPT 3 -#define MAX_HYLIAN_SHIELD_OPT 2 -#define MAX_HERO_TUNIC_OPT 2 -#define MAX_ZORA_ARMOR_OPT 2 -#define MAX_MAGIC_ARMOR_OPT 2 -#define MAX_BOMB_CAPACITY_OPT 2 -#define MAX_WALLET_OPT 3 -#define MAX_ARROW_CAPACITY_OPT 3 #define MAX_SCENT_OPT 6 -#define MAX_HIDDEN_SKILL_OPT 2 KEEP_VAR PauseData* pauseData; KEEP_FUNC PauseMenu::PauseMenu(Cursor& cursor) : Menu(cursor), - lines{{"ordon sword:", ORDON_SWORD_INDEX, "Wooden Sword / Ordon Sword", false, nullptr, - MAX_ORDON_SWORD_OPT}, - {"master sword:", MASTER_SWORD_INDEX, "Master Sword / Light Sword", false, nullptr, - MAX_MASTER_SWORD_OPT}, - {"wooden shield:", WOOD_SHIELD_INDEX, "Ordon Shield / Wooden Shield", false, nullptr, - MAX_WOOD_SHIELD_OPT}, - {"hylian shield:", HYLIAN_SHIELD_INDEX, "Hylian Shield", false, nullptr, - MAX_HYLIAN_SHIELD_OPT}, - {"hero's tunic:", HERO_TUNIC_INDEX, "Hero's Tunic", false, nullptr, MAX_HERO_TUNIC_OPT}, - {"zora armor:", ZORA_ARMOR_INDEX, "Zora Armor", false, nullptr, MAX_ZORA_ARMOR_OPT}, - {"magic armor:", MAGIC_ARMOR_INDEX, "Magic Armor", false, nullptr, MAX_MAGIC_ARMOR_OPT}, - {"bomb capacity:", BOMB_CAPACITY_INDEX, "Bomb Bag Capacity", false, nullptr, - MAX_BOMB_CAPACITY_OPT}, - {"wallet upgrade:", WALLET_INDEX, "Wallet Capacity", false, nullptr, MAX_WALLET_OPT}, - {"arrow capacity:", ARROW_CAPACITY_INDEX, "Arrow Quiver Capacity", false, nullptr, - MAX_ARROW_CAPACITY_OPT}, - {"scent:", SCENT_INDEX, "Current Scent", false, nullptr}, + lines{{"equipment", EQUIPMENT_INDEX, "Equipment", false, nullptr}, {"golden bugs", GOLDEN_BUG_INDEX, "Golden Bugs", false, nullptr}, - {"ending blow:", ENDING_BLOW_INDEX, "Ending Blow", true, [](){return pauseData->l_ebFlag;}}, - {"shield bash:", SHIELD_BASH_INDEX, "Shield Bash", true, [](){return pauseData->l_sbFlag;}}, - {"backslice:", BACKSLICE_INDEX, "Backslice", true, [](){return pauseData->l_bsFlag;}}, - {"helm splitter:", HELM_SPLITTER_INDEX, "Helm Splitter", true, [](){return pauseData->l_hsFlag;}}, - {"mortal draw:", MORTAL_DRAW_INDEX, "Mortal Draw", true, [](){return pauseData->l_mdFlag;}}, - {"jump strike:", JUMP_STRIKE_INDEX, "Jump Strike", true, [](){return pauseData->l_jsFlag;}}, - {"greatspin:", GREAT_SPIN_INDEX, "Greatspin", true, [](){return pauseData->l_gsFlag;}}} {} + {"hidden skills", HIDDEN_SKILL_INDEX, "Hidden Skills", false, nullptr}, + {"scent:", SCENT_INDEX, "Current Scent", false, nullptr}} {} PauseMenu::~PauseMenu() {} -void PauseMenu::resetIndex() { - pauseData->l_ordonSword_idx = 0; - pauseData->l_masterSword_idx = 0; - pauseData->l_woodShield_idx = 0; - pauseData->l_hyShield_idx = 0; - pauseData->l_tunic_idx = 0; - pauseData->l_zoraArmor_idx = 0; - pauseData->l_magicArmor_idx = 0; - pauseData->l_bombCap_idx = 0; - pauseData->l_wallet_idx = 0; - pauseData->l_arrowCap_idx = 0; - pauseData->l_scent_idx = 0; -} - -void PauseMenu::getEquipment() { - if (dComIfGs_isItemFirstBit(SWORD)) { - pauseData->l_ordonSword_idx = 2; - } else if (dComIfGs_isItemFirstBit(WOOD_STICK)) { - pauseData->l_ordonSword_idx = 1; - } - - if (dComIfGs_isItemFirstBit(LIGHT_SWORD)) { - pauseData->l_masterSword_idx = 2; - } else if (dComIfGs_isItemFirstBit(MASTER_SWORD)) { - pauseData->l_masterSword_idx = 1; - } - - if (dComIfGs_isItemFirstBit(SHIELD)) { - pauseData->l_woodShield_idx = 2; - } else if (dComIfGs_isItemFirstBit(WOOD_SHIELD)) { - pauseData->l_woodShield_idx = 1; - } - - if (dComIfGs_isItemFirstBit(HYLIA_SHIELD)) { - pauseData->l_hyShield_idx = 1; - } - - if (dComIfGs_isItemFirstBit(WEAR_KOKIRI)) { - pauseData->l_tunic_idx = 1; - } - - if (dComIfGs_isItemFirstBit(WEAR_ZORA)) { - pauseData->l_zoraArmor_idx = 1; - } - - if (dComIfGs_isItemFirstBit(ARMOR)) { - pauseData->l_magicArmor_idx = 1; - } - - if (dComIfGs_isItemFirstBit(BOMB_BAG_LV2)) { - pauseData->l_bombCap_idx = 1; - } - - switch (dComIfGs_getWalletSize()) { - case 1: - pauseData->l_wallet_idx = 1; - break; - case 2: - pauseData->l_wallet_idx = 2; - break; - } - - if (dComIfGs_getArrowMax() == 100) { - pauseData->l_arrowCap_idx = 2; - } else if (dComIfGs_getArrowMax() == 60) { - pauseData->l_arrowCap_idx = 1; - } +void PauseMenu::draw() { + cursor.setMode(Cursor::MODE_LIST); switch (dComIfGs_getCollectSmell()) { case 180: @@ -139,118 +42,39 @@ void PauseMenu::getEquipment() { pauseData->l_scent_idx = 0; } -} - -void PauseMenu::setEquipment() { - switch (pauseData->l_ordonSword_idx) { - case 0: - dComIfGs_offItemFirstBit(WOOD_STICK); - dComIfGs_offItemFirstBit(SWORD); - break; - case 1: - dComIfGs_onItemFirstBit(WOOD_STICK); - dComIfGs_offItemFirstBit(SWORD); - break; - case 2: - dComIfGs_onItemFirstBit(SWORD); - dComIfGs_offItemFirstBit(WOOD_STICK); - break; - } - switch (pauseData->l_masterSword_idx) { - case 0: - dComIfGs_offItemFirstBit(MASTER_SWORD); - dComIfGs_offItemFirstBit(LIGHT_SWORD); - break; - case 1: - dComIfGs_onItemFirstBit(MASTER_SWORD); - dComIfGs_offItemFirstBit(LIGHT_SWORD); - break; - case 2: - dComIfGs_onItemFirstBit(LIGHT_SWORD); - break; - } - - switch (pauseData->l_woodShield_idx) { - case 0: - dComIfGs_offItemFirstBit(SHIELD); - dComIfGs_offItemFirstBit(WOOD_SHIELD); - break; - case 1: - dComIfGs_onItemFirstBit(WOOD_SHIELD); - break; - case 2: - dComIfGs_onItemFirstBit(SHIELD); - break; - } - - switch (pauseData->l_hyShield_idx) { - case 0: - dComIfGs_offItemFirstBit(HYLIA_SHIELD); - break; - case 1: - dComIfGs_onItemFirstBit(HYLIA_SHIELD); - break; - } - - switch (pauseData->l_tunic_idx) { - case 0: - dComIfGs_offItemFirstBit(WEAR_KOKIRI); - break; - case 1: - dComIfGs_onItemFirstBit(WEAR_KOKIRI); - break; - } - - switch (pauseData->l_zoraArmor_idx) { - case 0: - dComIfGs_offItemFirstBit(WEAR_ZORA); - break; - case 1: - dComIfGs_onItemFirstBit(WEAR_ZORA); - break; + if (GZ_getButtonTrig(BACK_BUTTON)) { + g_menuMgr->pop(); + return; } - switch (pauseData->l_magicArmor_idx) { - case 0: - dComIfGs_offItemFirstBit(ARMOR); - break; - case 1: - dComIfGs_onItemFirstBit(ARMOR); - break; - } + ListMember scent_opt[6] = {"none", "youths' scent", "scent of ilia", "poe scent", "reekfish scent", "medicine scent"}; - switch (pauseData->l_bombCap_idx) { - case 0: - dComIfGs_offItemFirstBit(BOMB_BAG_LV2); - break; - case 1: - dComIfGs_onItemFirstBit(BOMB_BAG_LV2); - break; - } + switch (cursor.y) { + case SCENT_INDEX: + cursor.x = pauseData->l_scent_idx; + cursor.move(MAX_SCENT_OPT, MENU_LINE_NUM); - switch (pauseData->l_wallet_idx) { - case 0: - dComIfGs_setWalletSize(WALLET); - break; - case 1: - dComIfGs_setWalletSize(BIG_WALLET); + if (cursor.y == SCENT_INDEX) { + pauseData->l_scent_idx = cursor.x; + } break; - case 2: - dComIfGs_setWalletSize(GIANT_WALLET); + default: + cursor.move(0, MENU_LINE_NUM); break; } - switch (pauseData->l_arrowCap_idx) { - case 0: - dComIfGs_setArrowMax(30); - break; - case 1: - dComIfGs_setArrowMax(60); - break; - case 2: - dComIfGs_setArrowMax(100); - break; + if (GZ_getButtonTrig(SELECTION_BUTTON)) { + switch (cursor.y) { + case EQUIPMENT_INDEX: + g_menuMgr->push(MN_EQUIPMENT_INDEX); + return; + case GOLDEN_BUG_INDEX: + g_menuMgr->push(MN_GOLDEN_BUGS_INDEX); + return; + case HIDDEN_SKILL_INDEX: + g_menuMgr->push(MN_HIDDEN_SKILLS_INDEX); + } } switch (pauseData->l_scent_idx) { @@ -272,180 +96,7 @@ void PauseMenu::setEquipment() { default: dComIfGs_setCollectSmell(255); } -} - -void PauseMenu::draw() { - static bool init = false; - cursor.setMode(Cursor::MODE_LIST); - - if (!init) { - getEquipment(); - init = true; - } - - if (GZ_getButtonTrig(BACK_BUTTON)) { - init = false; - g_menuMgr->pop(); - resetIndex(); - return; - } - - // update hidden skill flags - pauseData->l_ebFlag = dComIfGs_isEventBit(0x2904); - pauseData->l_sbFlag = dComIfGs_isEventBit(0x2908); - pauseData->l_bsFlag = dComIfGs_isEventBit(0x2902); - pauseData->l_hsFlag = dComIfGs_isEventBit(0x2901); - pauseData->l_mdFlag = dComIfGs_isEventBit(0x2A80); - pauseData->l_jsFlag = dComIfGs_isEventBit(0x2A40); - pauseData->l_gsFlag = dComIfGs_isEventBit(0x2A20); - - ListMember ordonSword_opt[3] = {"none", "wooden sword", "ordon sword"}; - ListMember masterSword_opt[3] = {"none", "master sword", "light sword"}; - ListMember woodShield_opt[3] = {"none", "ordon shield", "wooden shield"}; - ListMember hyShield_opt[2] = {"none", "hylian shield"}; - ListMember tunic_opt[2] = {"none", "hero's tunic"}; - ListMember zoraArmor_opt[2] = {"none", "zora armor"}; - ListMember magicArmor_opt[2] = {"none", "magic armor"}; - ListMember bombCap_opt[2] = {"30/15/10", "60/30/20"}; - ListMember wallet_opt[3] = {"300 Rupees", "600 Rupees", "1000 Rupees"}; - ListMember arrowCap_opt[3] = {"30 Arrows", "60 Arrows", "100 Arrows"}; - ListMember scent_opt[6] = {"none", "youths' scent", "scent of ilia", "poe scent", "reekfish scent", "medicine scent"}; - - switch (cursor.y) { - case ORDON_SWORD_INDEX: - cursor.x = pauseData->l_ordonSword_idx; - cursor.move(MAX_ORDON_SWORD_OPT, MENU_LINE_NUM); - - if (cursor.y == ORDON_SWORD_INDEX) { - pauseData->l_ordonSword_idx = cursor.x; - } - break; - case MASTER_SWORD_INDEX: - cursor.x = pauseData->l_masterSword_idx; - cursor.move(MAX_MASTER_SWORD_OPT, MENU_LINE_NUM); - - if (cursor.y == MASTER_SWORD_INDEX) { - pauseData->l_masterSword_idx = cursor.x; - } - break; - case WOOD_SHIELD_INDEX: - cursor.x = pauseData->l_woodShield_idx; - cursor.move(MAX_WOOD_SHIELD_OPT, MENU_LINE_NUM); - - if (cursor.y == WOOD_SHIELD_INDEX) { - pauseData->l_woodShield_idx = cursor.x; - } - break; - case HYLIAN_SHIELD_INDEX: - cursor.x = pauseData->l_hyShield_idx; - cursor.move(MAX_HYLIAN_SHIELD_OPT, MENU_LINE_NUM); - - if (cursor.y == HYLIAN_SHIELD_INDEX) { - pauseData->l_hyShield_idx = cursor.x; - } - break; - case HERO_TUNIC_INDEX: - cursor.x = pauseData->l_tunic_idx; - cursor.move(MAX_HERO_TUNIC_OPT, MENU_LINE_NUM); - - if (cursor.y == HERO_TUNIC_INDEX) { - pauseData->l_tunic_idx = cursor.x; - } - break; - case ZORA_ARMOR_INDEX: - cursor.x = pauseData->l_zoraArmor_idx; - cursor.move(MAX_ZORA_ARMOR_OPT, MENU_LINE_NUM); - - if (cursor.y == ZORA_ARMOR_INDEX) { - pauseData->l_zoraArmor_idx = cursor.x; - } - break; - case MAGIC_ARMOR_INDEX: - cursor.x = pauseData->l_magicArmor_idx; - cursor.move(MAX_MAGIC_ARMOR_OPT, MENU_LINE_NUM); - - if (cursor.y == MAGIC_ARMOR_INDEX) { - pauseData->l_magicArmor_idx = cursor.x; - } - break; - case BOMB_CAPACITY_INDEX: - cursor.x = pauseData->l_bombCap_idx; - cursor.move(MAX_BOMB_CAPACITY_OPT, MENU_LINE_NUM); - - if (cursor.y == BOMB_CAPACITY_INDEX) { - pauseData->l_bombCap_idx = cursor.x; - } - break; - case WALLET_INDEX: - cursor.x = pauseData->l_wallet_idx; - cursor.move(MAX_WALLET_OPT, MENU_LINE_NUM); - - if (cursor.y == WALLET_INDEX) { - pauseData->l_wallet_idx = cursor.x; - } - break; - case ARROW_CAPACITY_INDEX: - cursor.x = pauseData->l_arrowCap_idx; - cursor.move(MAX_ARROW_CAPACITY_OPT, MENU_LINE_NUM); - - if (cursor.y == ARROW_CAPACITY_INDEX) { - pauseData->l_arrowCap_idx = cursor.x; - } - break; - case SCENT_INDEX: - cursor.x = pauseData->l_scent_idx; - cursor.move(MAX_SCENT_OPT, MENU_LINE_NUM); - - if (cursor.y == SCENT_INDEX) { - pauseData->l_scent_idx = cursor.x; - } - break; - default: - cursor.move(0, MENU_LINE_NUM); - break; - } - - if (GZ_getButtonTrig(SELECTION_BUTTON)) { - switch (cursor.y) { - case GOLDEN_BUG_INDEX: - g_menuMgr->push(MN_GOLDEN_BUGS_INDEX); - break; - case ENDING_BLOW_INDEX: - setEventFlag(0x2904); - break; - case SHIELD_BASH_INDEX: - setEventFlag(0x2908); - break; - case BACKSLICE_INDEX: - setEventFlag(0x2902); - break; - case HELM_SPLITTER_INDEX: - setEventFlag(0x2901); - break; - case MORTAL_DRAW_INDEX: - setEventFlag(0x2A80); - break; - case JUMP_STRIKE_INDEX: - setEventFlag(0x2A40); - break; - case GREAT_SPIN_INDEX: - setEventFlag(0x2A20); - break; - } - } - - setEquipment(); - lines[ORDON_SWORD_INDEX].printf(" <%s>", ordonSword_opt[pauseData->l_ordonSword_idx].member); - lines[MASTER_SWORD_INDEX].printf(" <%s>", masterSword_opt[pauseData->l_masterSword_idx].member); - lines[WOOD_SHIELD_INDEX].printf(" <%s>", woodShield_opt[pauseData->l_woodShield_idx].member); - lines[HYLIAN_SHIELD_INDEX].printf(" <%s>", hyShield_opt[pauseData->l_hyShield_idx].member); - lines[HERO_TUNIC_INDEX].printf(" <%s>", tunic_opt[pauseData->l_tunic_idx].member); - lines[ZORA_ARMOR_INDEX].printf(" <%s>", zoraArmor_opt[pauseData->l_zoraArmor_idx].member); - lines[MAGIC_ARMOR_INDEX].printf(" <%s>", magicArmor_opt[pauseData->l_magicArmor_idx].member); - lines[BOMB_CAPACITY_INDEX].printf(" <%s>", bombCap_opt[pauseData->l_bombCap_idx].member); - lines[WALLET_INDEX].printf(" <%s>", wallet_opt[pauseData->l_wallet_idx].member); - lines[ARROW_CAPACITY_INDEX].printf(" <%s>", arrowCap_opt[pauseData->l_arrowCap_idx].member); lines[SCENT_INDEX].printf(" <%s>", scent_opt[pauseData->l_scent_idx].member); GZ_drawMenuLines(lines, cursor.y, MENU_LINE_NUM);