From 129cd4a6567108d2678ec92c4382118326056fdf Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Wed, 21 Jan 2026 13:16:38 -0500 Subject: [PATCH] Added tab completion for bulk items, e.g. tab to craft something and it crafts all of them. Press tab to feed the fire and feed all items selected, --- src/crafting.nvgt | 753 ++++++++++++++++++++++++++++++++++++++- src/inventory_menus.nvgt | 254 +++++++++++++ 2 files changed, 1005 insertions(+), 2 deletions(-) diff --git a/src/crafting.nvgt b/src/crafting.nvgt index ab9d70a..efe45d5 100644 --- a/src/crafting.nvgt +++ b/src/crafting.nvgt @@ -81,6 +81,12 @@ void run_weapons_menu() { else if (selection == 1) craft_sling(); break; } + + if (key_pressed(KEY_TAB)) { + if (selection == 0) craft_spear_max(); + else if (selection == 1) craft_sling_max(); + break; + } } } @@ -128,6 +134,17 @@ void run_tools_menu() { else if (selection == 6) craft_clay_pot(); break; } + + if (key_pressed(KEY_TAB)) { + if (selection == 0) craft_knife_max(); + else if (selection == 1) craft_snare_max(); + else if (selection == 2) craft_axe_max(); + else if (selection == 3) craft_fishing_pole_max(); + else if (selection == 4) craft_rope_max(); + else if (selection == 5) craft_reed_basket_max(); + else if (selection == 6) craft_clay_pot_max(); + break; + } } } @@ -165,6 +182,12 @@ void run_materials_menu() { else if (selection == 1) craft_incense(); break; } + + if (key_pressed(KEY_TAB)) { + if (selection == 0) butcher_small_game_max(); + else if (selection == 1) craft_incense_max(); + break; + } } } void run_clothing_menu() { @@ -209,6 +232,16 @@ void run_clothing_menu() { else if (selection == 5) craft_skin_pouch(); break; } + + if (key_pressed(KEY_TAB)) { + if (selection == 0) craft_skin_hat_max(); + else if (selection == 1) craft_skin_gloves_max(); + else if (selection == 2) craft_skin_pants_max(); + else if (selection == 3) craft_skin_tunic_max(); + else if (selection == 4) craft_moccasins_max(); + else if (selection == 5) craft_skin_pouch_max(); + break; + } } } @@ -351,6 +384,15 @@ void run_barricade_menu() { else if (action == 3) reinforce_barricade_with_stones(); break; } + + if (key_pressed(KEY_TAB)) { + int action = action_types[selection]; + if (action == 0) reinforce_barricade_max_with_sticks(); + else if (action == 1) reinforce_barricade_max_with_vines(); + else if (action == 2) reinforce_barricade_max_with_log(); + else if (action == 3) reinforce_barricade_max_with_stones(); + break; + } } } @@ -363,7 +405,7 @@ void simulate_crafting(int item_count) { for(int i = 0; i < item_count; i++) { float pitch = random(85, 115); p.play_stationary_extended("sounds/crafting.ogg", false, 0, 0, 0, pitch); - + timer t; while(t.elapsed < 800) { wait(5); @@ -391,6 +433,29 @@ void craft_knife() { } } +void craft_knife_max() { + if (inv_knives >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more stone knives.", true); + return; + } + + int max_possible = inv_stones / 2; + int space = get_personal_stack_limit() - inv_knives; + if (max_possible > space) max_possible = space; + + if (max_possible <= 0) { + screen_reader_speak("Missing: 2 stones", true); + return; + } + + int total_cost = max_possible * 2; + int craft_time = (total_cost < max_possible * 4) ? max_possible * 4 : total_cost; + simulate_crafting(craft_time); + inv_stones -= (max_possible * 2); + inv_knives += max_possible; + screen_reader_speak("Crafted " + max_possible + " Stone Knives.", true); +} + void craft_spear() { string missing = ""; if (inv_knives < 1) missing += "Stone Knife "; @@ -414,6 +479,45 @@ void craft_spear() { } } +void craft_spear_max() { + if (inv_knives < 1) { + screen_reader_speak("Missing: Stone Knife", true); + return; + } + if (inv_spears >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more spears.", true); + return; + } + + int max_by_sticks = inv_sticks; + int max_by_vines = inv_vines; + int max_by_stones = inv_stones; + int max_craft = max_by_sticks; + if (max_by_vines < max_craft) max_craft = max_by_vines; + if (max_by_stones < max_craft) max_craft = max_by_stones; + + int space = get_personal_stack_limit() - inv_spears; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + string missing = ""; + if (inv_sticks < 1) missing += "1 stick "; + if (inv_vines < 1) missing += "1 vine "; + if (inv_stones < 1) missing += "1 stone "; + screen_reader_speak("Missing: " + missing, true); + return; + } + + int total_cost = max_craft * 3; // 1 stick + 1 vine + 1 stone per spear + int craft_time = (total_cost < max_craft * 4) ? max_craft * 4 : total_cost; + simulate_crafting(craft_time); + inv_sticks -= max_craft; + inv_vines -= max_craft; + inv_stones -= max_craft; + inv_spears += max_craft; + screen_reader_speak("Crafted " + max_craft + " Spears.", true); +} + void craft_sling() { string missing = ""; if (inv_skins < 1) missing += "1 skin "; @@ -434,6 +538,37 @@ void craft_sling() { } } +void craft_sling_max() { + if (inv_slings >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more slings.", true); + return; + } + + int max_by_skins = inv_skins; + int max_by_vines = inv_vines / 2; + int max_craft = max_by_skins; + if (max_by_vines < max_craft) max_craft = max_by_vines; + + int space = get_personal_stack_limit() - inv_slings; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + string missing = ""; + if (inv_skins < 1) missing += "1 skin "; + if (inv_vines < 2) missing += "2 vines "; + screen_reader_speak("Missing: " + missing, true); + return; + } + + int total_cost = max_craft * 3; // 1 skin + 2 vines per sling + int craft_time = (total_cost < max_craft * 4) ? max_craft * 4 : total_cost; + simulate_crafting(craft_time); + inv_skins -= max_craft; + inv_vines -= (max_craft * 2); + inv_slings += max_craft; + screen_reader_speak("Crafted " + max_craft + " Slings.", true); +} + void craft_skin_hat() { string missing = ""; if (inv_skins < 1) missing += "1 skin "; @@ -454,6 +589,37 @@ void craft_skin_hat() { } } +void craft_skin_hat_max() { + if (inv_skin_hats >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more skin hats.", true); + return; + } + + int max_by_skins = inv_skins; + int max_by_vines = inv_vines; + int max_craft = max_by_skins; + if (max_by_vines < max_craft) max_craft = max_by_vines; + + int space = get_personal_stack_limit() - inv_skin_hats; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + string missing = ""; + if (inv_skins < 1) missing += "1 skin "; + if (inv_vines < 1) missing += "1 vine "; + screen_reader_speak("Missing: " + missing, true); + return; + } + + int total_cost = max_craft * 2; // 1 skin + 1 vine per hat + int craft_time = (total_cost < max_craft * 4) ? max_craft * 4 : total_cost; + simulate_crafting(craft_time); + inv_skins -= max_craft; + inv_vines -= max_craft; + inv_skin_hats += max_craft; + screen_reader_speak("Crafted " + max_craft + " Skin Hats.", true); +} + void craft_skin_gloves() { string missing = ""; if (inv_skins < 1) missing += "1 skin "; @@ -474,6 +640,37 @@ void craft_skin_gloves() { } } +void craft_skin_gloves_max() { + if (inv_skin_gloves >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more skin gloves.", true); + return; + } + + int max_by_skins = inv_skins; + int max_by_vines = inv_vines; + int max_craft = max_by_skins; + if (max_by_vines < max_craft) max_craft = max_by_vines; + + int space = get_personal_stack_limit() - inv_skin_gloves; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + string missing = ""; + if (inv_skins < 1) missing += "1 skin "; + if (inv_vines < 1) missing += "1 vine "; + screen_reader_speak("Missing: " + missing, true); + return; + } + + int total_cost = max_craft * 2; // 1 skin + 1 vine per gloves + int craft_time = (total_cost < max_craft * 4) ? max_craft * 4 : total_cost; + simulate_crafting(craft_time); + inv_skins -= max_craft; + inv_vines -= max_craft; + inv_skin_gloves += max_craft; + screen_reader_speak("Crafted " + max_craft + " Skin Gloves.", true); +} + void craft_skin_pants() { string missing = ""; if (inv_skins < 6) missing += "6 skins "; @@ -494,6 +691,36 @@ void craft_skin_pants() { } } +void craft_skin_pants_max() { + if (inv_skin_pants >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more skin pants.", true); + return; + } + + int max_by_skins = inv_skins / 6; + int max_by_vines = inv_vines / 3; + int max_craft = max_by_skins; + if (max_by_vines < max_craft) max_craft = max_by_vines; + + int space = get_personal_stack_limit() - inv_skin_pants; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + string missing = ""; + if (inv_skins < 6) missing += "6 skins "; + if (inv_vines < 3) missing += "3 vines "; + screen_reader_speak("Missing: " + missing, true); + return; + } + + int total_cost = max_craft * 9; // 6 skins + 3 vines per pants + simulate_crafting(total_cost); + inv_skins -= (max_craft * 6); + inv_vines -= (max_craft * 3); + inv_skin_pants += max_craft; + screen_reader_speak("Crafted " + max_craft + " Skin Pants.", true); +} + void craft_skin_tunic() { string missing = ""; if (inv_skins < 4) missing += "4 skins "; @@ -514,6 +741,36 @@ void craft_skin_tunic() { } } +void craft_skin_tunic_max() { + if (inv_skin_tunics >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more skin tunics.", true); + return; + } + + int max_by_skins = inv_skins / 4; + int max_by_vines = inv_vines / 2; + int max_craft = max_by_skins; + if (max_by_vines < max_craft) max_craft = max_by_vines; + + int space = get_personal_stack_limit() - inv_skin_tunics; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + string missing = ""; + if (inv_skins < 4) missing += "4 skins "; + if (inv_vines < 2) missing += "2 vines "; + screen_reader_speak("Missing: " + missing, true); + return; + } + + int total_cost = max_craft * 6; // 4 skins + 2 vines per tunic + simulate_crafting(total_cost); + inv_skins -= (max_craft * 4); + inv_vines -= (max_craft * 2); + inv_skin_tunics += max_craft; + screen_reader_speak("Crafted " + max_craft + " Skin Tunics.", true); +} + void craft_moccasins() { string missing = ""; if (inv_skins < 2) missing += "2 skins "; @@ -534,6 +791,37 @@ void craft_moccasins() { } } +void craft_moccasins_max() { + if (inv_moccasins >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more moccasins.", true); + return; + } + + int max_by_skins = inv_skins / 2; + int max_by_vines = inv_vines; + int max_craft = max_by_skins; + if (max_by_vines < max_craft) max_craft = max_by_vines; + + int space = get_personal_stack_limit() - inv_moccasins; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + string missing = ""; + if (inv_skins < 2) missing += "2 skins "; + if (inv_vines < 1) missing += "1 vine "; + screen_reader_speak("Missing: " + missing, true); + return; + } + + int total_cost = max_craft * 3; // 2 skins + 1 vine per moccasins + int craft_time = (total_cost < max_craft * 4) ? max_craft * 4 : total_cost; + simulate_crafting(craft_time); + inv_skins -= (max_craft * 2); + inv_vines -= max_craft; + inv_moccasins += max_craft; + screen_reader_speak("Crafted " + max_craft + " Moccasins.", true); +} + void craft_skin_pouch() { string missing = ""; if (inv_skins < 2) missing += "2 skins "; @@ -554,6 +842,37 @@ void craft_skin_pouch() { } } +void craft_skin_pouch_max() { + if (inv_skin_pouches >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more skin pouches.", true); + return; + } + + int max_by_skins = inv_skins / 2; + int max_by_vines = inv_vines; + int max_craft = max_by_skins; + if (max_by_vines < max_craft) max_craft = max_by_vines; + + int space = get_personal_stack_limit() - inv_skin_pouches; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + string missing = ""; + if (inv_skins < 2) missing += "2 skins "; + if (inv_vines < 1) missing += "1 vine "; + screen_reader_speak("Missing: " + missing, true); + return; + } + + int total_cost = max_craft * 3; // 2 skins + 1 vine per pouch + int craft_time = (total_cost < max_craft * 4) ? max_craft * 4 : total_cost; + simulate_crafting(craft_time); + inv_skins -= (max_craft * 2); + inv_vines -= max_craft; + inv_skin_pouches += max_craft; + screen_reader_speak("Crafted " + max_craft + " Skin Pouches.", true); +} + void craft_snare() { string missing = ""; if (inv_sticks < 1) missing += "1 stick "; @@ -574,6 +893,37 @@ void craft_snare() { } } +void craft_snare_max() { + if (inv_snares >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more snares.", true); + return; + } + + int max_by_sticks = inv_sticks; + int max_by_vines = inv_vines / 2; + int max_craft = max_by_sticks; + if (max_by_vines < max_craft) max_craft = max_by_vines; + + int space = get_personal_stack_limit() - inv_snares; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + string missing = ""; + if (inv_sticks < 1) missing += "1 stick "; + if (inv_vines < 2) missing += "2 vines "; + screen_reader_speak("Missing: " + missing, true); + return; + } + + int total_cost = max_craft * 3; // 1 stick + 2 vines per snare + int craft_time = (total_cost < max_craft * 4) ? max_craft * 4 : total_cost; + simulate_crafting(craft_time); + inv_sticks -= max_craft; + inv_vines -= (max_craft * 2); + inv_snares += max_craft; + screen_reader_speak("Crafted " + max_craft + " Snares.", true); +} + void craft_axe() { string missing = ""; if (inv_knives < 1) missing += "Stone Knife "; @@ -597,6 +947,44 @@ void craft_axe() { } } +void craft_axe_max() { + if (inv_knives < 1) { + screen_reader_speak("Missing: Stone Knife", true); + return; + } + if (inv_axes >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more stone axes.", true); + return; + } + + int max_by_sticks = inv_sticks; + int max_by_vines = inv_vines; + int max_by_stones = inv_stones / 2; + int max_craft = max_by_sticks; + if (max_by_vines < max_craft) max_craft = max_by_vines; + if (max_by_stones < max_craft) max_craft = max_by_stones; + + int space = get_personal_stack_limit() - inv_axes; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + string missing = ""; + if (inv_sticks < 1) missing += "1 stick "; + if (inv_vines < 1) missing += "1 vine "; + if (inv_stones < 2) missing += "2 stones "; + screen_reader_speak("Missing: " + missing, true); + return; + } + + int total_cost = max_craft * 4; // 1 stick + 1 vine + 2 stones per axe + simulate_crafting(total_cost); + inv_sticks -= max_craft; + inv_vines -= max_craft; + inv_stones -= (max_craft * 2); + inv_axes += max_craft; + screen_reader_speak("Crafted " + max_craft + " Stone Axes.", true); +} + void craft_firepit() { // Check if there's already a firepit here if (get_firepit_at(x) != null) { @@ -835,6 +1223,110 @@ void reinforce_barricade_with_stones() { screen_reader_speak("Reinforced barricade with stones. +" + gained + " health. Now " + barricade_health + " of " + BARRICADE_MAX_HEALTH + ".", true); } +void reinforce_barricade_max_with_sticks() { + if (barricade_health >= BARRICADE_MAX_HEALTH) { + screen_reader_speak("Barricade is already at full health.", true); + return; + } + + if (inv_sticks < BARRICADE_STICK_COST) { + screen_reader_speak("Missing: " + BARRICADE_STICK_COST + " sticks", true); + return; + } + + int health_needed = BARRICADE_MAX_HEALTH - barricade_health; + int max_reinforcements = (health_needed + BARRICADE_STICK_HEALTH - 1) / BARRICADE_STICK_HEALTH; + int can_afford = inv_sticks / BARRICADE_STICK_COST; + + int to_do = (max_reinforcements < can_afford) ? max_reinforcements : can_afford; + int total_cost = to_do * BARRICADE_STICK_COST; + + simulate_crafting(total_cost); + inv_sticks -= total_cost; + barricade_health += (to_do * BARRICADE_STICK_HEALTH); + if (barricade_health > BARRICADE_MAX_HEALTH) barricade_health = BARRICADE_MAX_HEALTH; + + screen_reader_speak("Reinforced barricade " + to_do + " times with sticks. Health now " + barricade_health + ".", true); +} + +void reinforce_barricade_max_with_vines() { + if (barricade_health >= BARRICADE_MAX_HEALTH) { + screen_reader_speak("Barricade is already at full health.", true); + return; + } + + if (inv_vines < BARRICADE_VINE_COST) { + screen_reader_speak("Missing: " + BARRICADE_VINE_COST + " vines", true); + return; + } + + int health_needed = BARRICADE_MAX_HEALTH - barricade_health; + int max_reinforcements = (health_needed + BARRICADE_VINE_HEALTH - 1) / BARRICADE_VINE_HEALTH; + int can_afford = inv_vines / BARRICADE_VINE_COST; + + int to_do = (max_reinforcements < can_afford) ? max_reinforcements : can_afford; + int total_cost = to_do * BARRICADE_VINE_COST; + + simulate_crafting(total_cost); + inv_vines -= total_cost; + barricade_health += (to_do * BARRICADE_VINE_HEALTH); + if (barricade_health > BARRICADE_MAX_HEALTH) barricade_health = BARRICADE_MAX_HEALTH; + + screen_reader_speak("Reinforced barricade " + to_do + " times with vines. Health now " + barricade_health + ".", true); +} + +void reinforce_barricade_max_with_log() { + if (barricade_health >= BARRICADE_MAX_HEALTH) { + screen_reader_speak("Barricade is already at full health.", true); + return; + } + + if (inv_logs < BARRICADE_LOG_COST) { + screen_reader_speak("Missing: " + BARRICADE_LOG_COST + " log", true); + return; + } + + int health_needed = BARRICADE_MAX_HEALTH - barricade_health; + int max_reinforcements = (health_needed + BARRICADE_LOG_HEALTH - 1) / BARRICADE_LOG_HEALTH; + int can_afford = inv_logs / BARRICADE_LOG_COST; + + int to_do = (max_reinforcements < can_afford) ? max_reinforcements : can_afford; + int total_cost = to_do * BARRICADE_LOG_COST; + + simulate_crafting(total_cost); + inv_logs -= total_cost; + barricade_health += (to_do * BARRICADE_LOG_HEALTH); + if (barricade_health > BARRICADE_MAX_HEALTH) barricade_health = BARRICADE_MAX_HEALTH; + + screen_reader_speak("Reinforced barricade " + to_do + " times with log. Health now " + barricade_health + ".", true); +} + +void reinforce_barricade_max_with_stones() { + if (barricade_health >= BARRICADE_MAX_HEALTH) { + screen_reader_speak("Barricade is already at full health.", true); + return; + } + + if (inv_stones < BARRICADE_STONE_COST) { + screen_reader_speak("Missing: " + BARRICADE_STONE_COST + " stones", true); + return; + } + + int health_needed = BARRICADE_MAX_HEALTH - barricade_health; + int max_reinforcements = (health_needed + BARRICADE_STONE_HEALTH - 1) / BARRICADE_STONE_HEALTH; + int can_afford = inv_stones / BARRICADE_STONE_COST; + + int to_do = (max_reinforcements < can_afford) ? max_reinforcements : can_afford; + int total_cost = to_do * BARRICADE_STONE_COST; + + simulate_crafting(total_cost); + inv_stones -= total_cost; + barricade_health += (to_do * BARRICADE_STONE_HEALTH); + if (barricade_health > BARRICADE_MAX_HEALTH) barricade_health = BARRICADE_MAX_HEALTH; + + screen_reader_speak("Reinforced barricade " + to_do + " times with stones. Health now " + barricade_health + ".", true); +} + void craft_fishing_pole() { string missing = ""; if (inv_sticks < 1) missing += "1 stick "; @@ -855,6 +1347,37 @@ void craft_fishing_pole() { } } +void craft_fishing_pole_max() { + if (inv_fishing_poles >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more fishing poles.", true); + return; + } + + int max_by_sticks = inv_sticks; + int max_by_vines = inv_vines / 2; + int max_craft = max_by_sticks; + if (max_by_vines < max_craft) max_craft = max_by_vines; + + int space = get_personal_stack_limit() - inv_fishing_poles; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + string missing = ""; + if (inv_sticks < 1) missing += "1 stick "; + if (inv_vines < 2) missing += "2 vines "; + screen_reader_speak("Missing: " + missing, true); + return; + } + + int total_cost = max_craft * 3; // 1 stick + 2 vines per pole + int craft_time = (total_cost < max_craft * 4) ? max_craft * 4 : total_cost; + simulate_crafting(craft_time); + inv_sticks -= max_craft; + inv_vines -= (max_craft * 2); + inv_fishing_poles += max_craft; + screen_reader_speak("Crafted " + max_craft + " Fishing Poles.", true); +} + void craft_rope() { string missing = ""; if (inv_vines < 3) missing += "3 vines "; @@ -873,6 +1396,30 @@ void craft_rope() { } } +void craft_rope_max() { + if (inv_ropes >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more rope.", true); + return; + } + + int max_craft = inv_vines / 3; + + int space = get_personal_stack_limit() - inv_ropes; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + screen_reader_speak("Missing: 3 vines", true); + return; + } + + int total_cost = max_craft * 3; // 3 vines per rope + int craft_time = (total_cost < max_craft * 4) ? max_craft * 4 : total_cost; + simulate_crafting(craft_time); + inv_vines -= (max_craft * 3); + inv_ropes += max_craft; + screen_reader_speak("Crafted " + max_craft + " Rope.", true); +} + void craft_reed_basket() { string missing = ""; if (inv_reeds < 3) missing += "3 reeds "; @@ -891,6 +1438,30 @@ void craft_reed_basket() { } } +void craft_reed_basket_max() { + if (inv_reed_baskets >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more reed baskets.", true); + return; + } + + int max_craft = inv_reeds / 3; + + int space = get_personal_stack_limit() - inv_reed_baskets; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + screen_reader_speak("Missing: 3 reeds", true); + return; + } + + int total_cost = max_craft * 3; // 3 reeds per basket + int craft_time = (total_cost < max_craft * 4) ? max_craft * 4 : total_cost; + simulate_crafting(craft_time); + inv_reeds -= (max_craft * 3); + inv_reed_baskets += max_craft; + screen_reader_speak("Crafted " + max_craft + " Reed Baskets.", true); +} + void craft_clay_pot() { string missing = ""; if (inv_clay < 3) missing += "3 clay "; @@ -916,6 +1487,37 @@ void craft_clay_pot() { } } +void craft_clay_pot_max() { + // Check for fire within 3 tiles (can hear it) + WorldFire@ fire = get_fire_within_range(x, 3); + if (fire == null) { + screen_reader_speak("You need a fire within 3 tiles to craft clay pots.", true); + return; + } + + if (inv_clay_pots >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more clay pots.", true); + return; + } + + int max_craft = inv_clay / 3; + + int space = get_personal_stack_limit() - inv_clay_pots; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + screen_reader_speak("Missing: 3 clay", true); + return; + } + + int total_cost = max_craft * 3; // 3 clay per pot + int craft_time = (total_cost < max_craft * 4) ? max_craft * 4 : total_cost; + simulate_crafting(craft_time); + inv_clay -= (max_craft * 3); + inv_clay_pots += max_craft; + screen_reader_speak("Crafted " + max_craft + " Clay Pots.", true); +} + void craft_incense() { if (world_altars.length() == 0) { screen_reader_speak("You need an altar to craft incense.", true); @@ -943,6 +1545,45 @@ void craft_incense() { } } +void craft_incense_max() { + if (world_altars.length() == 0) { + screen_reader_speak("You need an altar to craft incense.", true); + return; + } + + if (inv_incense >= get_personal_stack_limit()) { + screen_reader_speak("You can't carry any more incense.", true); + return; + } + + int max_by_sticks = inv_sticks / INCENSE_STICK_COST; + int max_by_vines = inv_vines / INCENSE_VINE_COST; + int max_by_reeds = inv_reeds / INCENSE_REED_COST; + int max_craft = max_by_sticks; + if (max_by_vines < max_craft) max_craft = max_by_vines; + if (max_by_reeds < max_craft) max_craft = max_by_reeds; + + int space = get_personal_stack_limit() - inv_incense; + if (max_craft > space) max_craft = space; + + if (max_craft <= 0) { + string missing = ""; + if (inv_sticks < INCENSE_STICK_COST) missing += INCENSE_STICK_COST + " sticks "; + if (inv_vines < INCENSE_VINE_COST) missing += INCENSE_VINE_COST + " vines "; + if (inv_reeds < INCENSE_REED_COST) missing += INCENSE_REED_COST + " reed "; + screen_reader_speak("Missing: " + missing, true); + return; + } + + int total_cost = (max_craft * INCENSE_STICK_COST) + (max_craft * INCENSE_VINE_COST) + (max_craft * INCENSE_REED_COST); + simulate_crafting(total_cost); + inv_sticks -= (max_craft * INCENSE_STICK_COST); + inv_vines -= (max_craft * INCENSE_VINE_COST); + inv_reeds -= (max_craft * INCENSE_REED_COST); + inv_incense += max_craft; + screen_reader_speak("Crafted " + max_craft + " Incense.", true); +} + void butcher_small_game() { string missing = ""; @@ -995,10 +1636,118 @@ void butcher_small_game() { inv_skins++; screen_reader_speak("Butchered " + game_type + ". Got 1 meat and 1 skin.", true); } - + // Play sound p.play_stationary("sounds/items/miscellaneous.ogg", false); } else { screen_reader_speak("Missing: " + missing, true); } } + +void butcher_small_game_max() { + string missing = ""; + + // Check for knife + if (inv_knives < 1) { + screen_reader_speak("Missing: Stone Knife", true); + return; + } + + // Check for small game or boar + if (inv_small_game < 1 && inv_boar_carcasses < 1) { + screen_reader_speak("Missing: Game", true); + return; + } + + // Check for fire within 3 tiles (can hear it) + WorldFire@ fire = get_fire_within_range(x, 3); + if (fire == null) { + screen_reader_speak("You need a fire within 3 tiles to butcher.", true); + return; + } + + // Calculate space constraints + int meat_space = get_personal_stack_limit() - inv_meat; + int skins_space = get_personal_stack_limit() - inv_skins; + + if (meat_space <= 0) { + screen_reader_speak("You can't carry any more meat.", true); + return; + } + if (skins_space <= 0) { + screen_reader_speak("You can't carry any more skins.", true); + return; + } + + // Count available game + int total_game = inv_small_game + inv_boar_carcasses; + + // Determine limiting factor + int max_craft = total_game; + if (meat_space < max_craft) max_craft = meat_space; + if (skins_space < max_craft) max_craft = skins_space; + + if (max_craft <= 0) { + screen_reader_speak("No space for outputs.", true); + return; + } + + // Each game takes 1 unit of time to butcher, minimum 4 per item + int total_cost = max_craft; // 1 per game + int craft_time = (total_cost < max_craft * 4) ? max_craft * 4 : total_cost; + simulate_crafting(craft_time); + + // Process all game + int total_meat = 0; + int total_skins = 0; + int total_feathers = 0; + int total_down = 0; + int total_sinew = 0; + int geese_count = 0; + int boars_count = 0; + + for (int i = 0; i < max_craft; i++) { + string game_type = ""; + if (inv_boar_carcasses > 0) { + game_type = "boar carcass"; + inv_boar_carcasses--; + boars_count++; + } else { + game_type = inv_small_game_types[0]; + inv_small_game_types.remove_at(0); + inv_small_game--; + if (game_type == "goose") geese_count++; + } + + if (game_type == "goose") { + total_meat++; + total_feathers += random(3, 6); + total_down += random(1, 3); + } else if (game_type == "boar carcass") { + total_meat += random(2, 3); + total_skins += 3; + total_sinew += 2; + } else { + total_meat++; + total_skins++; + } + } + + // Add all outputs at once + inv_meat += total_meat; + inv_skins += total_skins; + inv_feathers += total_feathers; + inv_down += total_down; + inv_sinew += total_sinew; + + // Build result message + string result = "Butchered " + max_craft + " game. Got " + total_meat + " meat"; + if (total_skins > 0) result += ", " + total_skins + " skins"; + if (total_feathers > 0) result += ", feathers"; + if (total_down > 0) result += ", and down"; + if (total_sinew > 0) result += ", and " + total_sinew + " sinew"; + result += "."; + + screen_reader_speak(result, true); + p.play_stationary("sounds/items/miscellaneous.ogg", false); +} diff --git a/src/inventory_menus.nvgt b/src/inventory_menus.nvgt index 7e40d45..b1fda41 100644 --- a/src/inventory_menus.nvgt +++ b/src/inventory_menus.nvgt @@ -280,6 +280,57 @@ void deposit_item(int item_type) { screen_reader_speak("Deposited " + amount + " " + get_item_label(item_type) + ".", true); } +void deposit_item_max(int item_type) { + int available = get_personal_count(item_type); + if (available <= 0) { + screen_reader_speak("Nothing to deposit.", true); + return; + } + + int storage_total = get_storage_total_items(); + if (storage_total >= BASE_STORAGE_MAX) { + screen_reader_speak("Storage is full.", true); + return; + } + + int capacity = BASE_STORAGE_MAX - storage_total; + int item_storage = get_storage_count(item_type); + int item_capacity = BASE_STORAGE_MAX - item_storage; + int amount = (available < capacity) ? available : capacity; + if (amount > item_capacity) amount = item_capacity; + + if (item_type == ITEM_STICKS) { inv_sticks -= amount; storage_sticks += amount; } + else if (item_type == ITEM_VINES) { inv_vines -= amount; storage_vines += amount; } + else if (item_type == ITEM_REEDS) { inv_reeds -= amount; storage_reeds += amount; } + else if (item_type == ITEM_STONES) { inv_stones -= amount; storage_stones += amount; } + else if (item_type == ITEM_LOGS) { inv_logs -= amount; storage_logs += amount; } + else if (item_type == ITEM_CLAY) { inv_clay -= amount; storage_clay += amount; } + else if (item_type == ITEM_SMALL_GAME) { inv_small_game -= amount; storage_small_game += amount; move_small_game_to_storage(amount); } + else if (item_type == ITEM_MEAT) { inv_meat -= amount; storage_meat += amount; } + else if (item_type == ITEM_SKINS) { inv_skins -= amount; storage_skins += amount; } + else if (item_type == ITEM_FEATHERS) { inv_feathers -= amount; storage_feathers += amount; } + else if (item_type == ITEM_DOWN) { inv_down -= amount; storage_down += amount; } + else if (item_type == ITEM_INCENSE) { inv_incense -= amount; storage_incense += amount; } + else if (item_type == ITEM_SPEARS) { inv_spears -= amount; storage_spears += amount; } + else if (item_type == ITEM_SLINGS) { inv_slings -= amount; storage_slings += amount; } + else if (item_type == ITEM_AXES) { inv_axes -= amount; storage_axes += amount; } + else if (item_type == ITEM_SNARES) { inv_snares -= amount; storage_snares += amount; } + else if (item_type == ITEM_KNIVES) { inv_knives -= amount; storage_knives += amount; } + else if (item_type == ITEM_FISHING_POLES) { inv_fishing_poles -= amount; storage_fishing_poles += amount; } + else if (item_type == ITEM_ROPES) { inv_ropes -= amount; storage_ropes += amount; } + else if (item_type == ITEM_REED_BASKETS) { inv_reed_baskets -= amount; storage_reed_baskets += amount; } + else if (item_type == ITEM_CLAY_POTS) { inv_clay_pots -= amount; storage_clay_pots += amount; } + else if (item_type == ITEM_SKIN_HATS) { inv_skin_hats -= amount; storage_skin_hats += amount; } + else if (item_type == ITEM_SKIN_GLOVES) { inv_skin_gloves -= amount; storage_skin_gloves += amount; } + else if (item_type == ITEM_SKIN_PANTS) { inv_skin_pants -= amount; storage_skin_pants += amount; } + else if (item_type == ITEM_SKIN_TUNICS) { inv_skin_tunics -= amount; storage_skin_tunics += amount; } + else if (item_type == ITEM_MOCCASINS) { inv_moccasins -= amount; storage_moccasins += amount; } + else if (item_type == ITEM_SKIN_POUCHES) { inv_skin_pouches -= amount; storage_skin_pouches += amount; } + + cleanup_equipment_after_inventory_change(); + screen_reader_speak("Deposited " + amount + " " + get_item_label(item_type) + ".", true); +} + void withdraw_item(int item_type) { int available = get_storage_count(item_type); if (available <= 0) { @@ -326,6 +377,55 @@ void withdraw_item(int item_type) { screen_reader_speak("Withdrew " + amount + " " + get_item_label(item_type) + ".", true); } +void withdraw_item_max(int item_type) { + int available = get_storage_count(item_type); + if (available <= 0) { + screen_reader_speak("Nothing to withdraw.", true); + return; + } + + int personal_limit = get_personal_stack_limit(); + int current_personal = get_personal_count(item_type); + int space = personal_limit - current_personal; + + if (space <= 0) { + screen_reader_speak("Can't carry any more.", true); + return; + } + + int amount = (available < space) ? available : space; + + if (item_type == ITEM_STICKS) { storage_sticks -= amount; inv_sticks += amount; } + else if (item_type == ITEM_VINES) { storage_vines -= amount; inv_vines += amount; } + else if (item_type == ITEM_REEDS) { storage_reeds -= amount; inv_reeds += amount; } + else if (item_type == ITEM_STONES) { storage_stones -= amount; inv_stones += amount; } + else if (item_type == ITEM_LOGS) { storage_logs -= amount; inv_logs += amount; } + else if (item_type == ITEM_CLAY) { storage_clay -= amount; inv_clay += amount; } + else if (item_type == ITEM_SMALL_GAME) { storage_small_game -= amount; inv_small_game += amount; move_small_game_to_personal(amount); } + else if (item_type == ITEM_MEAT) { storage_meat -= amount; inv_meat += amount; } + else if (item_type == ITEM_SKINS) { storage_skins -= amount; inv_skins += amount; } + else if (item_type == ITEM_FEATHERS) { storage_feathers -= amount; inv_feathers += amount; } + else if (item_type == ITEM_DOWN) { storage_down -= amount; inv_down += amount; } + else if (item_type == ITEM_INCENSE) { storage_incense -= amount; inv_incense += amount; } + else if (item_type == ITEM_SPEARS) { storage_spears -= amount; inv_spears += amount; } + else if (item_type == ITEM_SLINGS) { storage_slings -= amount; inv_slings += amount; } + else if (item_type == ITEM_AXES) { storage_axes -= amount; inv_axes += amount; } + else if (item_type == ITEM_SNARES) { storage_snares -= amount; inv_snares += amount; } + else if (item_type == ITEM_KNIVES) { storage_knives -= amount; inv_knives += amount; } + else if (item_type == ITEM_FISHING_POLES) { storage_fishing_poles -= amount; inv_fishing_poles += amount; } + else if (item_type == ITEM_ROPES) { storage_ropes -= amount; inv_ropes += amount; } + else if (item_type == ITEM_REED_BASKETS) { storage_reed_baskets -= amount; inv_reed_baskets += amount; } + else if (item_type == ITEM_CLAY_POTS) { storage_clay_pots -= amount; inv_clay_pots += amount; } + else if (item_type == ITEM_SKIN_HATS) { storage_skin_hats -= amount; inv_skin_hats += amount; } + else if (item_type == ITEM_SKIN_GLOVES) { storage_skin_gloves -= amount; inv_skin_gloves += amount; } + else if (item_type == ITEM_SKIN_PANTS) { storage_skin_pants -= amount; inv_skin_pants += amount; } + else if (item_type == ITEM_SKIN_TUNICS) { storage_skin_tunics -= amount; inv_skin_tunics += amount; } + else if (item_type == ITEM_MOCCASINS) { storage_moccasins -= amount; inv_moccasins += amount; } + else if (item_type == ITEM_SKIN_POUCHES) { storage_skin_pouches -= amount; inv_skin_pouches += amount; } + + screen_reader_speak("Withdrew " + amount + " " + get_item_label(item_type) + ".", true); +} + void sacrifice_item(int item_type) { int available = get_personal_count(item_type); if (available <= 0) { @@ -372,6 +472,53 @@ void sacrifice_item(int item_type) { screen_reader_speak("Sacrificed 1 " + get_item_label_singular(item_type) + ". Favor +" + format_favor(favor_gain) + ". Total " + format_favor(favor) + ".", true); } +void sacrifice_item_max(int item_type) { + int available = get_personal_count(item_type); + if (available <= 0) { + screen_reader_speak("Nothing to sacrifice.", true); + return; + } + + double favor_per_item = get_item_favor_value(item_type); + + if (item_type == ITEM_STICKS) { inv_sticks = 0; } + else if (item_type == ITEM_VINES) { inv_vines = 0; } + else if (item_type == ITEM_REEDS) { inv_reeds = 0; } + else if (item_type == ITEM_STONES) { inv_stones = 0; } + else if (item_type == ITEM_LOGS) { inv_logs = 0; } + else if (item_type == ITEM_CLAY) { inv_clay = 0; } + else if (item_type == ITEM_SMALL_GAME) { + inv_small_game = 0; + inv_small_game_types.resize(0); + } + else if (item_type == ITEM_MEAT) { inv_meat = 0; } + else if (item_type == ITEM_SKINS) { inv_skins = 0; } + else if (item_type == ITEM_FEATHERS) { inv_feathers = 0; } + else if (item_type == ITEM_DOWN) { inv_down = 0; } + else if (item_type == ITEM_INCENSE) { inv_incense = 0; } + else if (item_type == ITEM_SPEARS) { inv_spears = 0; } + else if (item_type == ITEM_SLINGS) { inv_slings = 0; } + else if (item_type == ITEM_AXES) { inv_axes = 0; } + else if (item_type == ITEM_SNARES) { inv_snares = 0; } + else if (item_type == ITEM_KNIVES) { inv_knives = 0; } + else if (item_type == ITEM_FISHING_POLES) { inv_fishing_poles = 0; } + else if (item_type == ITEM_ROPES) { inv_ropes = 0; } + else if (item_type == ITEM_REED_BASKETS) { inv_reed_baskets = 0; } + else if (item_type == ITEM_CLAY_POTS) { inv_clay_pots = 0; } + else if (item_type == ITEM_SKIN_HATS) { inv_skin_hats = 0; } + else if (item_type == ITEM_SKIN_GLOVES) { inv_skin_gloves = 0; } + else if (item_type == ITEM_SKIN_PANTS) { inv_skin_pants = 0; } + else if (item_type == ITEM_SKIN_TUNICS) { inv_skin_tunics = 0; } + else if (item_type == ITEM_MOCCASINS) { inv_moccasins = 0; } + else if (item_type == ITEM_SKIN_POUCHES) { inv_skin_pouches = 0; } + + cleanup_equipment_after_inventory_change(); + double total_favor = favor_per_item * available; + favor += total_favor; + + screen_reader_speak("Sacrificed " + available + " " + get_item_label(item_type) + ". Favor +" + format_favor(total_favor) + ". Total " + format_favor(favor) + ".", true); +} + void build_personal_inventory_options(string[]@ options, int[]@ item_types) { options.resize(0); item_types.resize(0); @@ -523,6 +670,13 @@ void run_inventory_menu(bool allow_deposit) { if (selection >= options.length()) selection = 0; screen_reader_speak(options[selection], true); } + + if (allow_deposit && key_pressed(KEY_TAB)) { + deposit_item_max(item_types[selection]); + build_personal_inventory_options(options, item_types); + if (selection >= options.length()) selection = 0; + screen_reader_speak(options[selection], true); + } } } @@ -565,6 +719,13 @@ void run_storage_menu() { if (selection >= options.length()) selection = 0; screen_reader_speak(options[selection], true); } + + if (key_pressed(KEY_TAB)) { + withdraw_item_max(item_types[selection]); + build_storage_inventory_options(options, item_types); + if (selection >= options.length()) selection = 0; + screen_reader_speak(options[selection], true); + } } } @@ -620,6 +781,13 @@ void run_altar_menu() { if (selection >= options.length()) selection = 0; screen_reader_speak(options[selection], true); } + + if (key_pressed(KEY_TAB)) { + sacrifice_item_max(item_types[selection]); + build_personal_inventory_options(options, item_types); + if (selection >= options.length()) selection = 0; + screen_reader_speak(options[selection], true); + } } } @@ -686,6 +854,76 @@ void try_burn_incense() { screen_reader_speak("Incense burning. " + incense_hours_remaining + " hours remaining.", true); } +void try_feed_fire_stick_max(WorldFire@ fire) { + if (inv_sticks <= 0 || fire == null) { + screen_reader_speak("No sticks to feed fire.", true); + return; + } + + int amount = inv_sticks; + int fuel_added = amount * 300000; // 5 minutes per stick + inv_sticks = 0; + + fire.add_fuel(fuel_added); + p.play_stationary("sounds/actions/feed_fire.ogg", false); + screen_reader_speak("Dumped " + amount + " sticks into the fire.", true); +} + +void try_feed_fire_vine_max(WorldFire@ fire) { + if (inv_vines <= 0 || fire == null) { + screen_reader_speak("No vines to feed fire.", true); + return; + } + + int amount = inv_vines; + int fuel_added = amount * 60000; // 1 minute per vine + inv_vines = 0; + + fire.add_fuel(fuel_added); + p.play_stationary("sounds/actions/feed_fire.ogg", false); + screen_reader_speak("Dumped " + amount + " vines into the fire.", true); +} + +void try_feed_fire_log_max(WorldFire@ fire) { + if (inv_logs <= 0 || fire == null) { + screen_reader_speak("No logs to feed fire.", true); + return; + } + + int amount = inv_logs; + int fuel_added = amount * 720000; // 12 minutes per log + inv_logs = 0; + + fire.add_fuel(fuel_added); + p.play_stationary("sounds/actions/feed_fire.ogg", false); + screen_reader_speak("Dumped " + amount + " logs into the fire.", true); +} + +void try_burn_incense_max() { + if (world_altars.length() == 0) { + screen_reader_speak("No altar built.", true); + return; + } + if (inv_clay_pots <= 0) { + screen_reader_speak("You need a clay pot to burn incense.", true); + return; + } + if (inv_incense <= 0) { + screen_reader_speak("No incense to burn.", true); + return; + } + + int amount = inv_incense; + int total_hours = amount * INCENSE_HOURS_PER_STICK; + inv_incense = 0; + inv_clay_pots--; + + incense_hours_remaining += total_hours; + incense_burning = true; + + screen_reader_speak("Burned " + amount + " incense. +" + total_hours + " hours.", true); +} + void check_equipment_menu() { if (key_pressed(KEY_E)) { // Check if player has any equipment @@ -769,6 +1007,22 @@ void run_action_menu(int x) { } break; } + + if (key_pressed(KEY_TAB)) { + int action = action_types[selection]; + if (action == 0) { + screen_reader_speak("Can't do that.", true); + } else if (action == 1) { + try_feed_fire_stick_max(nearby_fire); + } else if (action == 2) { + try_feed_fire_vine_max(nearby_fire); + } else if (action == 3) { + try_feed_fire_log_max(nearby_fire); + } else if (action == 4) { + try_burn_incense_max(); + } + break; + } } }