From f80e3263a3db7643595e920b35e2d5f432461f59 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Sun, 25 Jan 2026 11:08:25 -0500 Subject: [PATCH] A few bug fixes. God speed gets added even with runed speed enhancement. Sounds shouldn't abruptly update after menu close any more. --- draugnorak.nvgt | 1 + src/environment.nvgt | 287 +++++++++++++++++++++----------------- src/inventory_items.nvgt | 8 +- src/menus/menu_utils.nvgt | 8 ++ 4 files changed, 176 insertions(+), 128 deletions(-) diff --git a/draugnorak.nvgt b/draugnorak.nvgt index bd540db..2b56f0a 100644 --- a/draugnorak.nvgt +++ b/draugnorak.nvgt @@ -84,6 +84,7 @@ void main() show_window("Draugnorak"); init_flying_creature_configs(); init_item_registry(); + init_search_pools(); bool game_started = false; while (!game_started) { diff --git a/src/environment.nvgt b/src/environment.nvgt index 3196143..b4e457e 100644 --- a/src/environment.nvgt +++ b/src/environment.nvgt @@ -183,6 +183,51 @@ class Tree { } Tree@[] trees; +const int SEARCH_POOL_STREAM_BANK = 0; +const int SEARCH_POOL_FOREST = 1; +const int SEARCH_POOL_STONE_TERRAIN = 2; +const int SEARCH_POOL_COUNT = 3; + +class SearchPool { + int[] item_types; + int[] weights; + string[] found_messages; + string[] terrain_tags; +} + +SearchPool@[] search_pools; +int[] search_mass_noun_items; + +void init_search_pools() { + // Add or adjust all terrain-based search content here. + // Keep item_types, weights, and found_messages aligned by index. + // Leave found_messages empty to use the auto "Found a/an X." or "Found X." logic. + // Use terrain_tags to map pool usage without touching perform_search(). + search_pools.resize(SEARCH_POOL_COUNT); + + @search_pools[SEARCH_POOL_STREAM_BANK] = SearchPool(); + search_pools[SEARCH_POOL_STREAM_BANK].item_types = { ITEM_REEDS, ITEM_CLAY }; + search_pools[SEARCH_POOL_STREAM_BANK].weights = { 30, 70 }; + search_pools[SEARCH_POOL_STREAM_BANK].found_messages = { "Found a reed.", "Found clay." }; + search_pools[SEARCH_POOL_STREAM_BANK].terrain_tags = { "stream_bank" }; + + @search_pools[SEARCH_POOL_FOREST] = SearchPool(); + search_pools[SEARCH_POOL_FOREST].item_types = { ITEM_STICKS, ITEM_VINES }; + search_pools[SEARCH_POOL_FOREST].weights = { 1, 1 }; + search_pools[SEARCH_POOL_FOREST].found_messages = { "Found a stick.", "Found a vine." }; + search_pools[SEARCH_POOL_FOREST].terrain_tags = { "forest", "deep_forest" }; + + @search_pools[SEARCH_POOL_STONE_TERRAIN] = SearchPool(); + search_pools[SEARCH_POOL_STONE_TERRAIN].item_types = { ITEM_STONES }; + search_pools[SEARCH_POOL_STONE_TERRAIN].weights = { 1 }; + search_pools[SEARCH_POOL_STONE_TERRAIN].found_messages = { "Found a stone." }; + search_pools[SEARCH_POOL_STONE_TERRAIN].terrain_tags = { "gravel", "stone", "hard_stone" }; + + // Mass nouns for auto "Found X." fallback (no article). + // Add new mass nouns here when adding search items that should not use "a/an". + search_mass_noun_items = { ITEM_CLAY }; +} + string get_tree_area_terrain(int areaStart, int areaEnd) { if (areaStart >= BASE_END + 1 && areaEnd <= GRASS_END) { return "grass"; @@ -505,6 +550,121 @@ void damage_tree(int target_x, int damage) { } } +string build_item_list(int[] item_types) { + string list_text = ""; + for (uint i = 0; i < item_types.length(); i++) { + string item_name = item_registry[item_types[i]].name; + if (i == 0) { + list_text = item_name; + } else if (i == item_types.length() - 1) { + if (item_types.length() == 2) { + list_text += " or " + item_name; + } else { + list_text += ", or " + item_name; + } + } else { + list_text += ", " + item_name; + } + } + return list_text; +} + +bool is_mass_noun_item(int item_type) { + for (uint i = 0; i < search_mass_noun_items.length(); i++) { + if (search_mass_noun_items[i] == item_type) { + return true; + } + } + return false; +} + +string get_auto_found_message(int item_type) { + string singular = item_registry[item_type].singular; + if (is_mass_noun_item(item_type)) { + return "Found " + singular + "."; + } + + string first_letter = singular.substr(0, 1); + if (first_letter == "a" || first_letter == "e" || first_letter == "i" || first_letter == "o" || first_letter == "u") { + return "Found an " + singular + "."; + } + return "Found a " + singular + "."; +} + +int get_search_weight(int[] weights, uint index) { + if (index >= weights.length()) { + return 1; + } + int weight = weights[index]; + if (weight <= 0) { + return 1; + } + return weight; +} + +bool try_find_weighted_resource(int[] item_types, int[] weights, string[] found_messages) { + if (item_types.length() == 0) { + return false; + } + + int total_weight = 0; + int[] available_indices; + available_indices.resize(0); + + for (uint i = 0; i < item_types.length(); i++) { + if (get_personal_count(item_types[i]) >= get_personal_stack_limit()) { + continue; + } + int weight = get_search_weight(weights, i); + total_weight += weight; + available_indices.insert_last(i); + } + + if (available_indices.length() == 0) { + speak_with_history("You can't carry any more " + build_item_list(item_types) + ".", true); + return true; + } + + int roll = random(1, total_weight); + int running_weight = 0; + uint chosen_index = available_indices[0]; + for (uint i = 0; i < available_indices.length(); i++) { + uint candidate_index = available_indices[i]; + int weight = get_search_weight(weights, candidate_index); + running_weight += weight; + if (roll <= running_weight) { + chosen_index = candidate_index; + break; + } + } + + int item_type = item_types[chosen_index]; + add_personal_count(item_type, 1); + play_item_collect_sound(item_registry[item_type].singular); + + if (found_messages.length() > chosen_index && found_messages[chosen_index] != "") { + speak_with_history(found_messages[chosen_index], true); + } else { + speak_with_history(get_auto_found_message(item_type), true); + } + return true; +} + +bool try_search_for_terrain(string terrain_type) { + for (uint i = 0; i < search_pools.length(); i++) { + if (search_pools[i] is null) { + continue; + } + for (uint j = 0; j < search_pools[i].terrain_tags.length(); j++) { + if (search_pools[i].terrain_tags[j] == terrain_type) { + return try_find_weighted_resource(search_pools[i].item_types, + search_pools[i].weights, search_pools[i].found_messages); + } + } + } + return false; +} + void perform_search(int current_x) { // First priority: Check for world drops on this tile or adjacent @@ -579,36 +739,7 @@ void perform_search(int current_x) } if (near_stream_bank) { - bool found_reed = random(1, 100) <= 30; - if (found_reed) { - if (get_personal_count(ITEM_REEDS) < get_personal_stack_limit()) { - add_personal_count(ITEM_REEDS, 1); - play_item_collect_sound("reed"); - speak_with_history("Found a reed.", true); - return; - } - } else { - if (get_personal_count(ITEM_CLAY) < get_personal_stack_limit()) { - add_personal_count(ITEM_CLAY, 1); - play_item_collect_sound("clay"); - speak_with_history("Found clay.", true); - return; - } - } - - if (!found_reed && get_personal_count(ITEM_REEDS) < get_personal_stack_limit()) { - add_personal_count(ITEM_REEDS, 1); - play_item_collect_sound("reed"); - speak_with_history("Found a reed.", true); - } else if (found_reed && get_personal_count(ITEM_CLAY) < get_personal_stack_limit()) { - add_personal_count(ITEM_CLAY, 1); - play_item_collect_sound("clay"); - speak_with_history("Found clay.", true); - } else if (found_reed) { - speak_with_history("You can't carry any more reeds.", true); - } else { - speak_with_history("You can't carry any more clay.", true); - } + try_search_for_terrain("stream_bank"); return; } @@ -706,101 +837,7 @@ void perform_search(int current_x) return; } - // Stone terrain - check for stones - bool is_stone_terrain = false; - - // Check base gravel area (20-34) - if (current_x >= GRAVEL_START && current_x <= GRAVEL_END) { - is_stone_terrain = true; - } - // Check expanded areas - else if (expanded_area_start != -1 && current_x >= expanded_area_start && current_x <= expanded_area_end) { - // Check for mountain terrain first - MountainRange@ mountain = get_mountain_at(current_x); - if (mountain !is null) { - string terrain = mountain.get_terrain_at(current_x); - if (terrain == "stone" || terrain == "hard_stone" || terrain == "gravel") { - is_stone_terrain = true; - } - } else { - // Regular expanded area - check terrain type - int index = current_x - expanded_area_start; - if (index >= 0 && index < int(expanded_terrain_types.length())) { - string terrain = expanded_terrain_types[index]; - // Handle "mountain:terrain" format from older saves - if (terrain.find("mountain:") == 0) { - terrain = terrain.substr(9); - } - if (terrain == "stone" || terrain == "hard_stone" || terrain == "gravel") { - is_stone_terrain = true; - } - } - } - } - - if (is_stone_terrain) - { - if (get_personal_count(ITEM_STONES) < get_personal_stack_limit()) - { - add_personal_count(ITEM_STONES, 1); - play_item_collect_sound("stone"); - speak_with_history("Found a stone.", true); - } - else - { - speak_with_history("You can't carry any more stones.", true); - } - return; - } - - // Forest terrain - check for sticks and vines - bool is_forest_terrain = false; - string current_terrain = ""; - - // Check expanded areas for forest/deep_forest - if (expanded_area_start != -1 && current_x >= expanded_area_start && current_x <= expanded_area_end) { - // Check for mountain terrain first - MountainRange@ mountain = get_mountain_at(current_x); - if (mountain !is null) { - current_terrain = mountain.get_terrain_at(current_x); - } else { - // Regular expanded area - check terrain type - int index = current_x - expanded_area_start; - if (index >= 0 && index < int(expanded_terrain_types.length())) { - current_terrain = expanded_terrain_types[index]; - // Handle "mountain:terrain" format from older saves - if (current_terrain.find("mountain:") == 0) { - current_terrain = current_terrain.substr(9); - } - } - } - if (current_terrain == "forest" || current_terrain == "deep_forest") { - is_forest_terrain = true; - } - } - - if (is_forest_terrain) - { - bool can_find_stick = get_personal_count(ITEM_STICKS) < get_personal_stack_limit(); - bool can_find_vine = get_personal_count(ITEM_VINES) < get_personal_stack_limit(); - - if (!can_find_stick && !can_find_vine) { - speak_with_history("You can't carry any more sticks or vines.", true); - return; - } - - // Random choice: if both available, 50/50. If only one, find that. - bool find_stick = can_find_stick && (!can_find_vine || random(0, 1) == 0); - - if (find_stick) { - add_personal_count(ITEM_STICKS, 1); - play_item_collect_sound("stick"); - speak_with_history("Found a stick.", true); - } else { - add_personal_count(ITEM_VINES, 1); - play_item_collect_sound("vine"); - speak_with_history("Found a vine.", true); - } + if (try_search_for_terrain(search_terrain)) { return; } diff --git a/src/inventory_items.nvgt b/src/inventory_items.nvgt index b967437..94da265 100644 --- a/src/inventory_items.nvgt +++ b/src/inventory_items.nvgt @@ -193,9 +193,11 @@ void update_max_health_from_equipment() { int rune_bonus = get_total_rune_walk_speed_bonus(); walk_speed = base_speed - rune_bonus; - // Apply blessing (if active and faster than current) - if (blessing_speed_active && BLESSING_WALK_SPEED < walk_speed) { - walk_speed = BLESSING_WALK_SPEED; + // Apply blessing bonus on top of existing speed + if (blessing_speed_active) { + int blessing_bonus = BASE_WALK_SPEED - BLESSING_WALK_SPEED; + if (blessing_bonus < 0) blessing_bonus = 0; + walk_speed -= blessing_bonus; } // Ensure minimum walk speed diff --git a/src/menus/menu_utils.nvgt b/src/menus/menu_utils.nvgt index 277af30..e32bccb 100644 --- a/src/menus/menu_utils.nvgt +++ b/src/menus/menu_utils.nvgt @@ -2,11 +2,19 @@ // Helper functions used across multiple menu systems void menu_background_tick() { + // Keep this list in sync with the main game loop to avoid pausing ambience/weather/time. update_time(); + update_crossfade(); + update_weather(); update_environment(); update_snares(); + update_streams(); update_fires(); update_zombies(); + update_bandits(); + update_boars(); + update_flying_creatures(); + update_world_drops(); update_blessings(); update_notifications();