diff --git a/README.md b/README.md index 2f815697f..912cb9f4d 100644 --- a/README.md +++ b/README.md @@ -12,28 +12,30 @@ An overlay for Spelunky 2 to help you with modding, exploring the depths of the You are strongly discouraged from using any modding tools in your actual online Steam installation as to prevent unlocking achievements, corrupting your savefile and cheating in the leaderboards. You should make a copy of your game somewhere else and install [Mr. Goldbergs Steam Emulator](https://gitlab.com/Mr_Goldberg/goldberg_emulator/-/releases) in the game directory. (TL;DR: Copy the steam_api64.dll from the zip to the offline game directory and create steam_appid.txt with the text `418530` in it.) Also block the modded installation in your firewall. If you break anything using this tool you get to keep both pieces. Do not report modding related bugs to BlitWorks. ## Features -Current features and their keyboard shortcuts: - - **F-keys**: Collapse/Show the window +Current features and their *default* keyboard shortcuts: - **F1**: Search and spawn entities where you're standing + **Enter**: Spawn entity + **Ctrl+Arrows**: Move spawn coordinates around you + **Ctrl+Enter**: Teleport to coordinates + + **Shift+Arrows**: Teleport to direction + + **Mouse left**: Spawn entity at mouse cursor + + **Mouse right**: Teleport to mouse cursor + Enter multiple numeric IDs like `526 560 570` to spawn them all at once. Useful for making a kit you can just paste in. - + Note: Item numbers can change between versions, so use the search to find the latest ones or check `Spelunky 2/entities.txt` - - **F2**: Spawn a warp door to any world, level and theme - + **Enter**: Spawn door. Set the appropriate theme too or you will get weird results. + - **F2**: Spawn doors to many places + + **Enter**: Spawn warp door + + **Shift+Enter**: Spawn back layer door - **F3**: Camera controls - + **Ctrl+Comma/Period**: Change the zoom level + + **Ctrl+,**: Zoom in + + **Ctrl+.**: Zoom out + + **Ctrl+Numbers**: Set zoom level + Lock horizontal scrolling with the *N*x buttons for *N* wide levels + Note: It only sets the *default* zoom level, which isn't used in camp or shops. + - **F9**: Options + + **Ctrl+M**: Toggle mouse controls (spawn/teleport) + + **Ctrl+G**: Toggle god mode - **F11**: Hide overlay - - **Ctrl+G**: Toggle god mode - - **Ctrl+M**: Toggle click events - - **Ctrl+Numbers**: Set zoom level - - **RAlt+Arrows**: Teleport to direction - - **Shift+Enter**: Spawn a door to back layer - - Spawn or teleport to mouse cursor (see options) - - Peaceful mode (*nothing* takes damage from anything) + +Check `Spelunky 2/hotkeys.ini` after running Overlunky to change shortcut keys and check `Spelunky 2/entities.txt` for a list of numerical entity IDs. ## Usage **[Download the latest release](https://github.com/spelunky-fyi/overlunky/releases/latest)** and extract anywhere. Run the program, leave it running and then start your game, or the other way around! Overlunky doesn't do any permanent changes to your game, it only exists when you run it. @@ -45,6 +47,10 @@ Current features and their keyboard shortcuts: - If your game crashes when actually trying to use the tools: + We're not currently compatible with modlunky2, sorry! + Some entities just crash the game, try to avoid them next time. + - If you're missing some overlay windows: + + Delete `Spelunky 2/imgui.ini` to reset tool window positions. + - If you mess up your keyboard shortcuts: + + Delete `Spelunky 2/hotkeys.ini` to reset shortcut keys. ## Development If you'd rather build it yourself or help with development, clone the repository, get some Rust and C++ build tools and run this to get started: diff --git a/crates/injected/cxx/ui.cpp b/crates/injected/cxx/ui.cpp index e8ff4d436..07e3927c6 100644 --- a/crates/injected/cxx/ui.cpp +++ b/crates/injected/cxx/ui.cpp @@ -176,8 +176,11 @@ void load_hotkeys(std::string file) { if(sscanf(line.c_str(), "%s = %i", inikey, &inival)) { - std::string keystring(inikey); - keys[keystring] = inival; + std::string keyname(inikey); + if(keys.find(keyname) != keys.end()) + { + keys[keyname] = inival; + } } } } @@ -277,213 +280,180 @@ bool pressed(std::string keyname, int wParam) return wParam == keycode; } +bool active(std::string window) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* current = g.NavWindow; + return current == ImGui::FindWindowByName(windows[window].c_str()); +} + bool process_keys( _In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam) { - if(nCode != WM_KEYDOWN) return false; + if(nCode != WM_KEYDOWN) + { + return false; + } if(pressed("hide_ui", wParam)) { hidegui = !hidegui; - return true; } else if (pressed("tool_entity", wParam)) { if(toggle("tool_entity")) { set_focus_entity = true; } - return true; } else if (pressed("tool_door", wParam)) { if(toggle("tool_door")) { set_focus_world = true; } - return true; } else if (pressed("tool_camera", wParam)) { if(toggle("tool_camera")) { set_focus_zoom = true; } - return true; } else if (pressed("tool_options", wParam)) { toggle("tool_options"); - return true; } else if (pressed("zoom_out", wParam)) { g_zoom += 1.0; set_zoom(); - return true; } else if (pressed("zoom_in", wParam)) { g_zoom -= 1.0; set_zoom(); - return true; } else if (pressed("zoom_default", wParam)) { g_zoom = 13.5; set_zoom(); - return true; } else if (pressed("zoom_3x", wParam)) { g_zoom = 23.08; set_zoom(); - return true; } else if (pressed("zoom_4x", wParam)) { g_zoom = 29.87; set_zoom(); - return true; } else if (pressed("zoom_5x", wParam)) { g_zoom = 36.66; set_zoom(); - return true; } else if (pressed("toggle_godmode", wParam)) { god = !god; godmode(god); - return true; } else if (pressed("toggle_mouse", wParam)) // M { clickevents = !clickevents; - return true; } else if (pressed("teleport_left", wParam)) { teleport(-1, 0, false); - return true; } else if (pressed("teleport_right", wParam)) { teleport(1, 0, false); - return true; } else if (pressed("teleport_up", wParam)) { teleport(0, 1, false); - return true; } else if (pressed("teleport_down", wParam)) { teleport(0, -1, false); - return true; } else if (pressed("spawn_layer_door", wParam)) { spawn_backdoor(0.0, 0.0); - return true; } else if(pressed("teleport", wParam)) { teleport(g_x, g_y, false); - return true; } else if (pressed("coordinate_left", wParam)) { g_x -= 1; - return true; } else if (pressed("coordinate_right", wParam)) { g_x += 1; - return true; } else if (pressed("coordinate_up", wParam)) { g_y += 1; - return true; } else if (pressed("coordinate_down", wParam)) { g_y -= 1; - return true; } else if (pressed("spawn_entity", wParam)) { spawn_entities(false); - return true; } else if (pressed("spawn_warp_door", wParam)) { spawn_door(0.0, 0.0, g_world, g_level, 1, g_to+1); - return true; } - - ImGuiContext& g = *GImGui; - ImGuiWindow* current = g.NavWindow; - - if(ImGui::GetIO().WantCaptureKeyboard) - { // In-window keys - int x = 0, y = 0; - - if(pressed("move_left", wParam)) - { - x = -1; - } - else if(pressed("move_right", wParam)) - { - x = 1; - } - else if(pressed("move_up", wParam)) - { - y = 1; - } - else if(pressed("move_down", wParam)) - { - y = -1; - } - else if (pressed("enter", wParam) && current == ImGui::FindWindowByName(windows["tool_entity"].c_str())) - { - spawn_entities(false); - return true; - } - else if (pressed("enter", wParam) && current == ImGui::FindWindowByName(windows["tool_door"].c_str())) - { - spawn_door(0.0, 0.0, g_world, g_level, 1, g_to+1); - return true; - } - else if (pressed("enter", wParam) && current == ImGui::FindWindowByName(windows["tool_camera"].c_str())) - { - set_zoom(); - return true; - } - - if (x == 0 && y == 0) - { - return false; - } - - // List navigation - if (y != 0) - { - if(current == ImGui::FindWindowByName(windows["tool_entity"].c_str())) - { - g_current_item = std::min(std::max(g_current_item - y, 0), (int)g_items.size() - 1); - } - else if(current == ImGui::FindWindowByName(windows["tool_door"].c_str())) - { - g_to = std::min(std::max(g_to - y, 0), 15); - } - } - if (x != 0) - { - return false; - } - return true; + else if (pressed("move_up", wParam) && (active("tool_entity") || active("entities"))) + { + g_current_item = std::min(std::max(g_current_item - 1, 0), (int)g_items.size() - 1); + scroll_to_entity = true; + } + else if (pressed("move_down", wParam) && (active("tool_entity") || active("entities"))) + { + g_current_item = std::min(std::max(g_current_item + 1, 0), (int)g_items.size() - 1); + scroll_to_entity = true; } + else if (pressed("enter", wParam) && (active("tool_entity") || active("entities"))) + { + spawn_entities(false); + } + else if (pressed("move_up", wParam) && active("tool_door")) + { + g_to = std::min(std::max(g_to - 1, 0), 15); + } + else if (pressed("move_down", wParam) && active("tool_door")) + { + g_to = std::min(std::max(g_to + 1, 0), 15); + } + else if (pressed("enter", wParam) && active("tool_door")) + { + spawn_door(0.0, 0.0, g_world, g_level, 1, g_to+1); + } + else if (pressed("move_up", wParam) && active("tool_camera")) + { + g_zoom -= 1.0; + set_zoom(); + } + else if (pressed("move_down", wParam) && active("tool_camera")) + { + g_zoom += 1.0; + set_zoom(); + } + else if (pressed("enter", wParam) && active("tool_camera")) + { + set_zoom(); + } + else + { + return false; + } + return true; } void init_imgui() @@ -832,6 +802,7 @@ HRESULT __stdcall hkPresent(IDXGISwapChain *pSwapChain, UINT SyncInterval, UINT windows["tool_door"] = "Door to anywhere ("+key_string(keys["tool_door"])+")"; windows["tool_camera"] = "Camera ("+key_string(keys["tool_camera"])+")"; windows["tool_options"] = "Options ("+key_string(keys["tool_options"])+")"; + windows["entities"] = "##Entities"; } ImGui_ImplDX11_NewFrame();