diff --git a/docs/generate.py b/docs/generate.py index 37f449ac2..74f6e5e07 100644 --- a/docs/generate.py +++ b/docs/generate.py @@ -153,7 +153,10 @@ def print_lf(lf): "- This doc is up to date for the Overlunky [WHIP build](https://github.com/spelunky-fyi/overlunky/releases/tag/whip) and Playlunky [nightly build](https://github.com/spelunky-fyi/Playlunky/releases/tag/nightly). If you're using a stable release from the past, you might find some things here don't work." ) print( - "- Set `OL_DEBUG=1` in the same environment where the game is running to keep the Overlunky terminal open for better debug prints. This could be `cmd` or even the system environment variables if playing on Steam. Playlunky will also print the messages to terminal (even from Overlunky) if ran with the `-console` switch." + "- Use `Overlunky.exe --console` command line switch to keep the Overlunky terminal open for better debug prints. Playlunky will also print the messages to terminal (even from Overlunky) if ran with the `-console` switch." +) +print( + "- Testing functions, exploring the types, and most inline Lua examples in here can be used in the in-game REPL console, default opened with the tilde key or regional equivalent. Full script examples can be found in the Overlunky Scripts menu if the script bundle is installed." ) print("\n## External Function Library") diff --git a/docs/src/includes/_home.md b/docs/src/includes/_home.md index 4efbe5a83..13560a5e4 100644 --- a/docs/src/includes/_home.md +++ b/docs/src/includes/_home.md @@ -8,7 +8,8 @@ - This doc and the examples are written for a person who already knows [how to program in Lua](http://lua-users.org/wiki/TutorialDirectory). - This doc doesn't cover how to actually load scripts. Check the [README](https://github.com/spelunky-fyi/overlunky/#scripts) for instructions. - This doc is up to date for the Overlunky [WHIP build](https://github.com/spelunky-fyi/overlunky/releases/tag/whip) and Playlunky [nightly build](https://github.com/spelunky-fyi/Playlunky/releases/tag/nightly). If you're using a stable release from the past, you might find some things here don't work. -- Set `OL_DEBUG=1` in the same environment where the game is running to keep the Overlunky terminal open for better debug prints. This could be `cmd` or even the system environment variables if playing on Steam. Playlunky will also print the messages to terminal (even from Overlunky) if ran with the `-console` switch. +- Use `Overlunky.exe --console` command line switch to keep the Overlunky terminal open for better debug prints. Playlunky will also print the messages to terminal (even from Overlunky) if ran with the `-console` switch. +- Testing functions, exploring the types, and most inline Lua examples in here can be used in the in-game REPL console, default opened with the tilde key or regional equivalent. Full script examples can be found in the Overlunky Scripts menu if the script bundle is installed. ## External Function Library If you use a text editor/IDE that has a Lua linter available you can download [spel2.lua](https://raw.githubusercontent.com/spelunky-fyi/overlunky/main/docs/game_data/spel2.lua), place it in a folder of your choice and specify that folder as a "external function library". For example [VSCode](https://code.visualstudio.com/) with the [Lua Extension](https://marketplace.visualstudio.com/items?itemName=sumneko.lua) offers this feature. This will allow you to get auto-completion of API functions along with linting diff --git a/src/injected/ui.cpp b/src/injected/ui.cpp index ba51d4dc9..99e20e146 100644 --- a/src/injected/ui.cpp +++ b/src/injected/ui.cpp @@ -230,6 +230,7 @@ std::map default_keys{ {"speedhack_slow", VK_NEXT}, {"toggle_uncapped_fps", OL_KEY_CTRL | OL_KEY_SHIFT | 'U'}, {"respawn", OL_KEY_CTRL | 'R'}, + {"clear_messages", OL_KEY_CTRL | VK_BACK}, //{ "", 0x }, }; @@ -284,7 +285,7 @@ std::vector g_selected_ids; bool set_focus_entity = false, set_focus_world = false, set_focus_finder = false, set_focus_uid = false, scroll_to_entity = false, scroll_top = false, click_teleport = false, throw_held = false, show_app_metrics = false, lock_entity = false, lock_player = false, freeze_last = false, freeze_level = false, freeze_total = false, hide_ui = false, - enable_noclip = false, load_script_dir = true, load_packs_dir = false, enable_camp_camera = true, enable_camera_bounds = true, freeze_quest_yang = false, freeze_quest_sisters = false, freeze_quest_horsing = false, freeze_quest_sparrow = false, freeze_quest_tusk = false, freeze_quest_beg = false, run_finder = false, in_menu = false, zooming = false, g_inv = false, edit_last_id = false, edit_achievements = false, peek_layer = false, death_disable = false; + enable_noclip = false, enable_camp_camera = true, enable_camera_bounds = true, freeze_quest_yang = false, freeze_quest_sisters = false, freeze_quest_horsing = false, freeze_quest_sparrow = false, freeze_quest_tusk = false, freeze_quest_beg = false, run_finder = false, in_menu = false, zooming = false, g_inv = false, edit_last_id = false, edit_achievements = false, peek_layer = false, death_disable = false; std::optional quest_yang_state, quest_sisters_state, quest_horsing_state, quest_sparrow_state, quest_tusk_state, quest_beg_state; Entity* g_entity = 0; Entity* g_held_entity = 0; @@ -381,6 +382,8 @@ std::map options = { {"pause_last_instance", false}, {"update_check", true}, {"modifiers_clear_input", true}, + {"load_scripts", true}, + {"load_packs", false}, }; double g_engine_fps = 60.0, g_unfocused_fps = 33.0; @@ -803,7 +806,7 @@ bool SliderByte(const char* label, char* value, char min = 0, char max = 0, cons void refresh_script_files() { g_script_files.clear(); - if (load_script_dir && std::filesystem::exists(scriptpath) && std::filesystem::is_directory(scriptpath)) + if (options["load_scripts"] && std::filesystem::exists(scriptpath) && std::filesystem::is_directory(scriptpath)) { for (const auto& file : std::filesystem::directory_iterator(scriptpath)) { @@ -813,7 +816,7 @@ void refresh_script_files() } } } - else if (!load_script_dir && std::filesystem::exists(scriptpath) && std::filesystem::is_directory(scriptpath)) + else if (!options["load_scripts"] && std::filesystem::exists(scriptpath) && std::filesystem::is_directory(scriptpath)) { std::vector unload_scripts; for (const auto& script : g_scripts) @@ -831,7 +834,7 @@ void refresh_script_files() } } - if (load_packs_dir && std::filesystem::exists("Mods/Packs") && std::filesystem::is_directory("Mods/Packs")) + if (options["load_packs"] && std::filesystem::exists("Mods/Packs") && std::filesystem::is_directory("Mods/Packs")) { for (const auto& file : std::filesystem::recursive_directory_iterator("Mods/Packs")) { @@ -841,7 +844,7 @@ void refresh_script_files() } } } - else if (!load_packs_dir && std::filesystem::exists("Mods/Packs") && std::filesystem::is_directory("Mods/Packs")) + else if (!options["load_packs"] && std::filesystem::exists("Mods/Packs") && std::filesystem::is_directory("Mods/Packs")) { std::vector unload_scripts; for (const auto& script : g_scripts) @@ -1319,9 +1322,16 @@ void smart_delete(Entity* ent, bool unsafe = false) { static auto first_door = to_id("ENT_TYPE_FLOOR_DOOR_ENTRANCE"); static auto logical_door = to_id("ENT_TYPE_LOGICAL_DOOR"); - ent->flags = set_flag(ent->flags, 1); - for (auto item : ent->items.entities()) - item->flags = set_flag(item->flags, 1); + if (!ent->is_player()) + ent->flags = set_flag(ent->flags, 1); + if ((ent->type->search_flags & 0x80) == 0) + { + for (auto item : ent->items.entities()) + { + if (!item->is_player()) + item->flags = set_flag(item->flags, 1); + } + } UI::safe_destroy(ent, unsafe); if ((ent->type->id >= first_door && ent->type->id <= first_door + 15) || ent->type->id == logical_door) { @@ -2818,6 +2828,16 @@ void load_state(int slot) UI::copy_state(slot, 5); } +void clear_script_messages() +{ + for (auto& [name, script] : g_scripts) + script->consume_messages(); + for (auto& [name, script] : g_ui_scripts) + script->consume_messages(); + g_Console->consume_messages(); + g_ConsoleMessages.clear(); +} + bool process_keys(UINT nCode, WPARAM wParam, [[maybe_unused]] LPARAM lParam) { ImGuiContext& g = *GImGui; @@ -3559,6 +3579,10 @@ bool process_keys(UINT nCode, WPARAM wParam, [[maybe_unused]] LPARAM lParam) { load_state(4); } + else if (pressed("clear_messages", wParam)) + { + clear_script_messages(); + } else { return false; @@ -5161,7 +5185,7 @@ void render_clickhandler() { g_bucket->overlunky->hovered_uid = -1; } - if (options["draw_entity_tooltip"] && ImGui::IsWindowHovered()) + if (options["draw_entity_tooltip"] && ImGui::IsWindowHovered() && io.MouseDrawCursor) { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {4.0f, 4.0f}); tooltip(coords.c_str(), true); @@ -5519,7 +5543,7 @@ void render_clickhandler() g_held_entity->flags = g_held_flags; set_pos(startpos); set_vel(mouse_pos()); - if (g_held_entity && g_held_entity->is_movable()) + if (g_held_entity && g_held_entity->is_movable() && drag_delta("mouse_grab_throw") > 10.0f) UI::move_entity(g_held_id, g_x, g_y, true, g_vx, g_vy, options["snap_to_grid"]); g_x = 0; g_y = 0; @@ -5533,7 +5557,7 @@ void render_clickhandler() io.MouseDrawCursor = true; if (g_held_entity) g_held_entity->flags = g_held_flags; - if (options["snap_to_grid"] && g_held_entity->is_movable()) + if (options["snap_to_grid"] && g_held_entity->is_movable() && (drag_delta("mouse_grab") > 10.0f || drag_delta("mouse_grab_unsafe") > 10.0f)) { UI::move_entity(g_held_id, g_x, g_y, true, 0, 0, options["snap_to_grid"]); } @@ -6512,13 +6536,17 @@ void render_scripts() ImGui::SameLine(); ImGui::Checkbox("to console##ConsoleScriptMessages", &options["console_script_messages"]); ImGui::Checkbox("Fade script messages##FadeScriptMessages", &options["fade_script_messages"]); - if (ImGui::Checkbox("Load scripts from script directory##LoadScriptsDefault", &load_script_dir)) + ImGui::SameLine(); + if (ImGui::Button("Clear##ClearMessages")) + clear_script_messages(); + tooltip("Clear all script messages from screen", "clear_messages"); + if (ImGui::Checkbox("Load scripts from script directory##LoadScriptsDefault", &options["load_scripts"])) refresh_script_files(); ImGui::SameLine(); - if (ImGui::Button("Set##SetScriptDir")) + if (ImGui::Button("Change##SetScriptDir")) set_script_dir(); tooltip(scriptpath.c_str()); - if (ImGui::Checkbox("Load scripts from Mods/Packs##LoadScriptsPacks", &load_packs_dir)) + if (ImGui::Checkbox("Load scripts from Mods/Packs##LoadScriptsPacks", &options["load_packs"])) refresh_script_files(); if (ImGui::Button("Create new quick script")) { diff --git a/src/injected/ui_util.cpp b/src/injected/ui_util.cpp index 3e792d0a3..c24df6699 100644 --- a/src/injected/ui_util.cpp +++ b/src/injected/ui_util.cpp @@ -348,6 +348,8 @@ void UI::steam_achievements(bool on) } int32_t UI::destroy_entity_items(Entity* ent) { + if (ent->type->search_flags & 0x80) + return 0; auto items = entity_get_items_by(ent->uid, 0, 0); if (items.size() == 0) return -1; @@ -356,6 +358,8 @@ int32_t UI::destroy_entity_items(Entity* ent) while (it != items.rend()) { auto item = get_entity_ptr(*it); + if (item->type->search_flags & 0x81) + continue; UI::destroy_entity_items(item); UI::safe_destroy(item, false, false); it++;