# libstorm-nvgt Reusable NVGT helpers for Storm projects. ## Modules - `multikey.nvgt`: Helper functions for handling multiple equivalent keys. - `file_viewer.nvgt`: Accessible text/file viewer and optional editor. - `text_reader_compat.nvgt`: Optional aliases (`text_reader*`) for legacy code. - `ui.nvgt`: Dialog wrappers with optional main-window restoration. - `speech_history.nvgt`: `speak_with_history()` wrapper plus comma/period history navigation. - `notifications.nvgt`: Queued notifications with history and optional sound playback. - `menu_helpers.nvgt`: Simple menu runner + filter helpers with `sounds/menu` defaults. - `audio_paths.nvgt`: Shared `.ogg` / `.wav` audio path resolution helper. - `learn_sounds.nvgt`: Reusable learn-sounds browser with project-level exclusion/description hooks. - `docs_browser.nvgt`: Reusable document discovery/opening helpers for menus. - `dict_utils.nvgt`: Typed dictionary access helpers. - `save_utils.nvgt`: Generic save file I/O and AES helpers. - `name_sanitize.nvgt`: Name normalization and safe filename builders. - `crash_logger.nvgt`: Timestamped logging and unhandled exception logging helpers. - `volume_controls.nvgt`: Reusable global volume key handling and sound handle cleanup. ## Usage ```nvgt #include "libstorm-nvgt/multikey.nvgt" #include "libstorm-nvgt/file_viewer.nvgt" #include "libstorm-nvgt/text_reader_compat.nvgt" // Optional legacy aliases #include "libstorm-nvgt/ui.nvgt" #include "libstorm-nvgt/speech_history.nvgt" #include "libstorm-nvgt/notifications.nvgt" #include "libstorm-nvgt/menu_helpers.nvgt" #include "libstorm-nvgt/learn_sounds.nvgt" #include "libstorm-nvgt/docs_browser.nvgt" #include "libstorm-nvgt/dict_utils.nvgt" #include "libstorm-nvgt/save_utils.nvgt" #include "libstorm-nvgt/name_sanitize.nvgt" #include "libstorm-nvgt/crash_logger.nvgt" #include "libstorm-nvgt/volume_controls.nvgt" ``` ## multikey Example ```nvgt array jumpKeys = {KEY_UP, KEY_W, KEY_SPACE}; array runKeys = {KEY_LCTRL, KEY_RCTRL}; if (check_key_down(runKeys)) { moveInterval = 100; } if (check_key_down(jumpKeys) && !isJumping) { isJumping = true; } ``` ## ui Example ```nvgt ui_set_default_window_title("My Game"); string playerName = ui_input_box("New Game", "Enter your name", ""); if (ui_question("Confirm", "Start with this name?") == 1) { ui_info_box("New Game", "Ready", "Starting game now."); } ``` ## menu_helpers Examples ```nvgt string[] options = {"New Game", "Load Game", "Exit"}; int selected = menu_run_simple("Main menu.", options, true, 0, "sounds/menu"); if (selected == 2 || selected == -1) { exit(); } ``` ```nvgt // Prefix filtering helper usage in custom loops. string filterText = ""; int[] filteredIndices; string[] filteredOptions; int selection = 0; menu_apply_prefix_filter(filterText, options, filteredIndices, filteredOptions); bool changed = menu_update_prefix_filter(filterText, options, filteredIndices, filteredOptions, selection); ``` ## file_viewer Example ```nvgt file_viewer_file("README.txt", "Readme", true); ``` ## speech_history + notifications Example ```nvgt #include "libstorm-nvgt/speech_history.nvgt" #include "libstorm-nvgt/notifications.nvgt" void speak_notification_with_history(const string &in message, bool interrupt) { speak_with_history(message, interrupt); } void boot() { notifications_set_sound_path("sounds/notify"); notifications_set_speak_callback(speak_notification_with_history); speak_with_history("Game loaded.", true); } void game_loop_tick() { notifications_update(); notifications_check_keys(); check_speech_history_keys(); } void on_event() { notifications_enqueue("A resident has returned."); } ``` ## learn_sounds Example (Project Override File) ```nvgt // In your project root, create excluded_sounds.nvgt: void configure_project_learn_sounds() { learn_sounds_reset_configuration(); learn_sounds_add_skip_entry("sounds/menu/"); learn_sounds_add_description("sounds/actions/falling.ogg", "Lowers in pitch as the fall progresses."); } ``` ```nvgt // In your game module: #include "libstorm-nvgt/learn_sounds.nvgt" #include "excluded_sounds.nvgt" #include "libstorm-nvgt/speech_history.nvgt" void learn_sounds_bridge_speak(const string &in message, bool interrupt) { speak_with_history(message, interrupt); } void configure_and_run_learn_sounds() { learn_sounds_set_speak_callback(learn_sounds_bridge_speak); learn_sounds_set_menu_sound_dir("sounds/menu"); learn_sounds_set_root_dir("sounds"); configure_project_learn_sounds(); learn_sounds_run_menu(); } ``` ## save_utils + name_sanitize Example ```nvgt string filename = build_filename_from_name("Thora", ".dat", 40, "character"); save_encrypted_file(filename, serialize(saveData), "my_game_save_key"); ``` ## dict_utils + crash_logger Example ```nvgt double dayNumber = dict_get_number(saveData, "time_current_day", 1); if (has_exception()) { log_unhandled_exception_to_file("crash.log", "load_game"); } ``` ## volume_controls Example ```nvgt void on_volume_applied(float volumeDb) { sound_master_volume = volumeDb; } void init_audio() { volume_controls_set_apply_callback(on_volume_applied); volume_controls_configure(-60.0f, 0.0f, 3.0f, 0.0f); } void tick() { volume_controls_handle_keys(KEY_PAGEDOWN, KEY_PAGEUP, true); } ```