From 50e2ae835b43a1b48169d34f951fb057e2de6231 Mon Sep 17 00:00:00 2001 From: FireMario211 <17692105+FireMario211@users.noreply.github.com> Date: Wed, 26 Jun 2024 15:53:18 -0400 Subject: [PATCH] a LOTTA changes! --- .github/workflows/build-noimgui.yml | 2 +- .github/workflows/build.yml | 2 +- CMakeLists.txt | 2 +- build.sh | 2 +- changelog.md | 15 +++- mod.json | 14 ++-- resources/hacks/creator.json | 4 +- resources/hacks/global.json | 5 ++ resources/hacks/misc.json | 2 +- resources/hacks/player.json | 10 +++ resources/langs/czech.json | 2 +- resources/langs/french.json | 2 +- resources/langs/german.json | 2 +- resources/langs/greek.json | 2 +- resources/langs/japanese.json | 2 +- resources/langs/malay.json | 2 +- resources/langs/polish.json | 2 +- resources/langs/russian.json | 2 +- resources/langs/spanish.json | 2 +- resources/langs/template.json | 20 +++++- resources/langs/turkish.json | 2 +- resources/langs/ukrainian.json | 6 +- resources/langs/vietnamese-original.json | 2 +- resources/langs/vietnamese.json | 2 +- src/Hacks/Bypass.cpp | 10 +-- src/Hacks/Global.cpp | 15 ++-- src/Hacks/Player.cpp | 8 +++ src/Hacks/Quartz.cpp | 91 ++++++++++++++++++------ src/ImGui.cpp | 3 + src/Themes.cpp | 42 +++++++---- src/UI/PrismUI.cpp | 84 +++++++++++----------- src/UI/PrismUI.hpp | 4 ++ src/hacks.hpp | 1 + src/main.cpp | 44 +++++++++--- 34 files changed, 289 insertions(+), 121 deletions(-) diff --git a/.github/workflows/build-noimgui.yml b/.github/workflows/build-noimgui.yml index c692f4f..eef5d3c 100644 --- a/.github/workflows/build-noimgui.yml +++ b/.github/workflows/build-noimgui.yml @@ -31,7 +31,7 @@ jobs: build-config: 'RelWithDebInfo' export-pdb: true combine: true - sdk: 'nightly' + #sdk: 'nightly' target: ${{ matrix.config.target }} package: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a2a1c09..cbcbdf9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ jobs: build-config: 'RelWithDebInfo' export-pdb: true combine: true - sdk: 'nightly' + #sdk: 'nightly' target: ${{ matrix.config.target }} package: diff --git a/CMakeLists.txt b/CMakeLists.txt index deaa7a6..eaf21aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,7 +45,7 @@ endif() set(IMGUI_VERSION "v1.90") if (NOT APPLE AND NOT DEFINED ENV{NO_IMGUI}) - CPMAddPackage("gh:matcool/gd-imgui-cocos#5bc72d6") # specify a commit! + CPMAddPackage("gh:matcool/gd-imgui-cocos#09a9555") # specify a commit! target_link_libraries(${PROJECT_NAME} imgui-cocos) endif() diff --git a/build.sh b/build.sh index db9c2ba..e4a0030 100644 --- a/build.sh +++ b/build.sh @@ -1,4 +1,4 @@ -export GEODE_SDK=/home/fire/.geodenightly # remove when geode 2.0.0 is released +#export GEODE_SDK=/home/fire/.geodenightly # remove when geode 2.0.0 is released export SPLAT_DIR=/home/fire/xwin/splat export TOOLCHAIN_REPO=/home/fire/xwin/toolchain export GEODE_BINDINGS_REPO_PATH=/home/fire/.geodebindings diff --git a/changelog.md b/changelog.md index 616703f..f81663b 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,18 @@ +# v1.8.0 + - Added "Hide Level" + - Added "Hide Player" + - Added "No Rotate" + - Added importing functionality back + - "Noclip Accuracy" now only shows if Noclip is enabled + - Allowed the next frame button to work even at the end of the frame (Macro Editor) + - Fixed bug with the Prism Button bugging out if you switch between windowed and full screen + - Fixed a bug with the previous frame button going to the negatives on Android + - Added a geode setting to "Force Hide Button" + - Added "Custom Object Bypass" for Android + - (hopefully) Fixed the hold bug when using Macro Editor + - (hopefully) Fixed the ImGui font issue # v1.7.4 - - Update to support Goede Beta 1 + - Update to support Geode Beta 1 # v1.7.3 - Update Russian translations - Update Turkish translations diff --git a/mod.json b/mod.json index da598c2..b0ae612 100644 --- a/mod.json +++ b/mod.json @@ -1,6 +1,6 @@ { - "geode": "3.0.0-beta.1", - "version": "v1.7.4", + "geode": "3.1.1", + "version": "v1.8.0", "gd": { "win": "2.206", "mac": "2.206", @@ -18,7 +18,6 @@ "tags": ["cheats", "gameplay", "utility", "customization"], "resources": { "files": [ - "resources/icon.png", "resources/Screenshot1.png", "resources/checkmark.png", "resources/checkmark-hd.png", @@ -32,7 +31,8 @@ "resources/langs/*.json" ], "sprites": [ - "resources/infoIcon.png" + "resources/infoIcon.png", + "resources/icon.png" ], "fonts": { "PrismMenu": { @@ -50,6 +50,12 @@ "type": "bool", "default": false }, + "hide-button": { + "name": "Force Hide Button", + "description": "Hides the button in any menu and pause menu. (Requires restart)", + "type": "bool", + "default": false + }, "values": { "name": "Hack Values", "description": "NONE", diff --git a/resources/hacks/creator.json b/resources/hacks/creator.json index bcc7145..44bef27 100644 --- a/resources/hacks/creator.json +++ b/resources/hacks/creator.json @@ -52,7 +52,7 @@ ], "android64": [ {"addr": "0x6a1a24", "on": "20 00 80 52", "off": "56 d4 0f 94", "instruction": "mov w0, #1"}, - {"addr": "0x69d2ec", "on": "20 00 80 52", "off": "a4 d3 0f 94"}, + {"addr": "0x6a1cec", "on": "20 00 80 52", "off": "a4 d3 0f 94"}, {"addr": "0x6a1b00", "on": "20 00 80 52", "off": "ef c0 0f 94"} ], "iosold2.200": [ @@ -63,7 +63,7 @@ }, "type": "bool", "save": false, - "platforms": ["win"] + "platforms": ["win", "android32", "android64"] }, { "name": "No (C) Mark", diff --git a/resources/hacks/global.json b/resources/hacks/global.json index a5b3930..d974f38 100644 --- a/resources/hacks/global.json +++ b/resources/hacks/global.json @@ -45,6 +45,11 @@ "type": "bool", "platforms": ["win", "android32", "android64"] }, + { + "name": "Hide Level", + "desc": "Hides all objects in the level.", + "type": "bool" + }, { "name": "No Transition", "desc": "Shorterns scene transition time to 0s.", diff --git a/resources/hacks/misc.json b/resources/hacks/misc.json index 56dc98a..82ef24a 100644 --- a/resources/hacks/misc.json +++ b/resources/hacks/misc.json @@ -37,7 +37,7 @@ }, { "name": "Noclip Accuracy", - "desc": "Informs you how accurate your noclip run is. (Will not work without Anticheat Bypass enabled)", + "desc": "Informs you how accurate your noclip run is.", "type": "bool" }, { diff --git a/resources/hacks/player.json b/resources/hacks/player.json index 6c993b1..89ab21d 100644 --- a/resources/hacks/player.json +++ b/resources/hacks/player.json @@ -62,11 +62,21 @@ "type": "bool", "platforms": ["win", "android32", "android64"] }, + { + "name": "Hide Player", + "desc": "Hides the player. (Requires playing the level again)", + "type": "bool" + }, { "name": "No Trail", "desc": "Disables any trail effect from the player.", "type": "bool" }, + { + "name": "No Rotate", + "desc": "Freezes the player from rotating when jumping, or falling.", + "type": "bool" + }, { "name": "No Wave Trail", "desc": "Disables the trail behind the wave.", diff --git a/resources/langs/czech.json b/resources/langs/czech.json index 084869b..16fd7e8 100644 --- a/resources/langs/czech.json +++ b/resources/langs/czech.json @@ -425,7 +425,7 @@ { "Noclip Accuracy": { "name": "Noclip Přesnost", - "desc": "Informuje tě jak přesný je tvůj noclip run. (Nefunguje bez zapnutí Anticheat Bypass)" + "desc": "Informuje tě jak přesný je tvůj noclip run." } }, { diff --git a/resources/langs/french.json b/resources/langs/french.json index 3bcb79c..3602ffc 100644 --- a/resources/langs/french.json +++ b/resources/langs/french.json @@ -421,7 +421,7 @@ { "Noclip Accuracy": { "name": "Précision du Noclip", - "desc": "Vous informe à quel point votre run en Noclip est précise. (Ne marche qu'avec l'Anticheat Bypass actif)" + "desc": "Vous informe à quel point votre run en Noclip est précise." } }, { diff --git a/resources/langs/german.json b/resources/langs/german.json index b086f25..bfe2e61 100644 --- a/resources/langs/german.json +++ b/resources/langs/german.json @@ -433,7 +433,7 @@ { "Noclip Accuracy": { "name": "Noclip Übereinstimmung", - "desc": "Sagt dir wie genau dein Noclip run war. (Wird nicht ohne aktiviertem Anticheat Bypass funktionieren)." + "desc": "Sagt dir wie genau dein Noclip run war." } }, { diff --git a/resources/langs/greek.json b/resources/langs/greek.json index 18f300a..f618cc5 100644 --- a/resources/langs/greek.json +++ b/resources/langs/greek.json @@ -434,7 +434,7 @@ { "Noclip Accuracy": { "name": "Noclip Accuracy", - "desc": "Informs you how accurate your noclip run is. (Will not work without Anticheat Bypass enabled)" + "desc": "Informs you how accurate your noclip run is." } }, { diff --git a/resources/langs/japanese.json b/resources/langs/japanese.json index 117d5e3..b87f6b4 100644 --- a/resources/langs/japanese.json +++ b/resources/langs/japanese.json @@ -433,7 +433,7 @@ { "Noclip Accuracy": { "name": "ノークリップ正確率", - "desc": "ノークリップのプレイの正確さを表示します。(不正行為防止の迂回が有効になっていなければならない)" + "desc": "ノークリップのプレイの正確さを表示します。" } }, { diff --git a/resources/langs/malay.json b/resources/langs/malay.json index 20bc0eb..003ad67 100644 --- a/resources/langs/malay.json +++ b/resources/langs/malay.json @@ -432,7 +432,7 @@ { "Noclip Accuracy": { "name": "Rakaman Tepat Tanpa Klip", - "desc": "Memaklumkan anda betapa tepat larian tanpa klip anda. (Tidak akan berfungsi tanpa Pintasan Anti Menipu didayakan)" + "desc": "Memaklumkan anda betapa tepat larian tanpa klip anda." } }, { diff --git a/resources/langs/polish.json b/resources/langs/polish.json index d319783..4fbc728 100644 --- a/resources/langs/polish.json +++ b/resources/langs/polish.json @@ -433,7 +433,7 @@ { "Noclip Accuracy": { "name": "Dokładność Noclip", - "desc": "Pokazuje, z jaką dokładnością przechodzisz poziom z użyciem Noclip (Nie działa bez opcji Wyłącz Anticheat)" + "desc": "Pokazuje, z jaką dokładnością przechodzisz poziom z użyciem Noclip." } }, { diff --git a/resources/langs/russian.json b/resources/langs/russian.json index a07afe4..3633dd3 100644 --- a/resources/langs/russian.json +++ b/resources/langs/russian.json @@ -443,7 +443,7 @@ { "Noclip Accuracy": { "name": "Noclip Accuracy", - "desc": "Сообщает, насколько аккуратка ваша Noclip попытка. (Не работает без обхода античита)" + "desc": "Сообщает, насколько аккуратка ваша Noclip попытка." } }, { diff --git a/resources/langs/spanish.json b/resources/langs/spanish.json index 2c6de3c..4950ffd 100644 --- a/resources/langs/spanish.json +++ b/resources/langs/spanish.json @@ -438,7 +438,7 @@ { "Noclip Accuracy": { "name": "Noclip Accuracy", - "desc": "Le informa qué tan precisa es su ejecución de noclip. (No funcionará sin Anticheat Bypass habilitado)" + "desc": "Le informa qué tan precisa es su ejecución de noclip." } }, { diff --git a/resources/langs/template.json b/resources/langs/template.json index c6f4014..eb02f02 100644 --- a/resources/langs/template.json +++ b/resources/langs/template.json @@ -434,7 +434,7 @@ { "Noclip Accuracy": { "name": "Noclip Accuracy", - "desc": "Informs you how accurate your noclip run is. (Will not work without Anticheat Bypass enabled)" + "desc": "Informs you how accurate your noclip run is." } }, { @@ -618,5 +618,23 @@ "name": "Menu Keybind", "desc": "The keybind for opening the Prism Menu UI!" } + }, + { + "Hide Level": { + "name": "Hide Level", + "desc": "Hides all objects in the level." + } + }, + { + "Hide Player": { + "name": "Hide Level", + "desc": "Hides the player. (Requires playing the level again)" + } + }, + { + "No Rotate": { + "name": "No Rotate", + "desc": "Freezes the player from rotating when jumping, or falling." + } } ] diff --git a/resources/langs/turkish.json b/resources/langs/turkish.json index 4c02015..2e8a7d3 100644 --- a/resources/langs/turkish.json +++ b/resources/langs/turkish.json @@ -440,7 +440,7 @@ { "Noclip Accuracy": { "name": "Noclip Doğruluğu", - "desc": "Noclip etkinken seviyeyi ne kadar doğru oynadığınızı size bildirir. (Anti-Hile Baypas etkinleştirilmeden çalışmaz)" + "desc": "Noclip etkinken seviyeyi ne kadar doğru oynadığınızı size bildirir." } }, { diff --git a/resources/langs/ukrainian.json b/resources/langs/ukrainian.json index 9b50792..a6aa055 100644 --- a/resources/langs/ukrainian.json +++ b/resources/langs/ukrainian.json @@ -434,7 +434,7 @@ { "Noclip Accuracy": { "name": "Точність з ноукліпом", - "desc": "Інформує про те, наскільки точною є ваша гра з ноукліпом. (Не працює без ввімкненого Обходу античіта)" + "desc": "Інформує про те, наскільки точною є ваша гра з ноукліпом." } }, { @@ -531,7 +531,7 @@ }, { "Playback": { - "name": "Проргравання", + "name": "Програвання", "desc": "Програє макрос." } }, @@ -555,7 +555,7 @@ }, { "Import Macro": { - "name": "Імпротувати макрос", + "name": "Імпортувати макрос", "desc": "Імпортує макрос." } }, diff --git a/resources/langs/vietnamese-original.json b/resources/langs/vietnamese-original.json index 7efaef6..d50a27f 100644 --- a/resources/langs/vietnamese-original.json +++ b/resources/langs/vietnamese-original.json @@ -439,7 +439,7 @@ { "Noclip Accuracy": { "name": "Độ chính xác của Noclip", - "desc": "Thông báo cho bạn mức độ chính xác của lần chạy noclip của bạn. (Sẽ không hoạt động nếu không bật Anticheat Bypass)" + "desc": "Thông báo cho bạn mức độ chính xác của lần chạy noclip của bạn." } }, { diff --git a/resources/langs/vietnamese.json b/resources/langs/vietnamese.json index 52b3098..470179a 100644 --- a/resources/langs/vietnamese.json +++ b/resources/langs/vietnamese.json @@ -439,7 +439,7 @@ { "Noclip Accuracy": { "name": "Do chinh xac cua Noclip", - "desc": "Thong bao cho ban muc do chinh xac cua lan chay noclip cua ban. (Se khong hoat dong neu khong bat Anticheat Bypass)" + "desc": "Thong bao cho ban muc do chinh xac cua lan chay noclip cua ban." } }, { diff --git a/src/Hacks/Bypass.cpp b/src/Hacks/Bypass.cpp index e4ea934..3225bc1 100644 --- a/src/Hacks/Bypass.cpp +++ b/src/Hacks/Bypass.cpp @@ -9,12 +9,14 @@ using namespace geode::prelude; // Icon Bypass class $modify(GameManager) { bool isIconUnlocked(int _id, IconType _type) { - if (!Hacks::isHackEnabled("Icon Bypass") || Hacks::isHackEnabled("Enable Patching")) return GameManager::isIconUnlocked(_id, _type); - return true; + if (GameManager::isIconUnlocked(_id, _type)) return true; + if (_id <= 0) return false; + //if (_id >= GameManager::countForType(_type)) return false; + return Hacks::isHackEnabled("Icon Bypass"); } bool isColorUnlocked(int _id, UnlockType _type) { - if (!Hacks::isHackEnabled("Icon Bypass") || Hacks::isHackEnabled("Enable Patching")) return GameManager::isColorUnlocked(_id, _type); - return true; + if (GameManager::isColorUnlocked(_id, _type)) return true; + return Hacks::isHackEnabled("Icon Bypass"); } }; diff --git a/src/Hacks/Global.cpp b/src/Hacks/Global.cpp index f2016a4..f7c565a 100644 --- a/src/Hacks/Global.cpp +++ b/src/Hacks/Global.cpp @@ -75,6 +75,12 @@ class $modify(PlayLayer) { obj->m_isHide = false; if (obj->m_objectID == 1007) return; } + if (Hacks::isHackEnabled("Layout Mode") || Hacks::isHackEnabled("Hide Level")) { + // probably a bad idea! + std::unordered_set colorTriggers = { 221, 743, 744, 899, 900, 915, 1006 }; + + if (colorTriggers.find(obj->m_objectID) != colorTriggers.end()) return; + } if (Hacks::isHackEnabled("No Glow")) { obj->m_hasNoGlow = true; } @@ -82,15 +88,12 @@ class $modify(PlayLayer) { } }; - -// Layout Mode +// Layout Mode, Hide Level class $modify(GameObject) { void setVisible(bool v) { + if (Hacks::isHackEnabled("Hide Level") && m_objectID != 0) return GameObject::setVisible(false); if (!Hacks::isHackEnabled("Layout Mode")) return GameObject::setVisible(v); - //m_hasGroupParent == 0 - std::vector outerPortal = {}; - //i really dont want to have to check every single object id - if (m_objectType == GameObjectType::Decoration && m_objectID != 44) { // 44 being practice mode checkpoint, because thats a "decoration" + if (m_objectType == GameObjectType::Decoration && m_objectID != 44 && m_objectID != 38 && m_objectID != 749 && m_objectID != 747) { // 44 being practice mode checkpoint, because thats a "decoration" GameObject::setVisible(false); } else { GameObject::setVisible(v); diff --git a/src/Hacks/Player.cpp b/src/Hacks/Player.cpp index 4164a68..421f930 100644 --- a/src/Hacks/Player.cpp +++ b/src/Hacks/Player.cpp @@ -83,6 +83,14 @@ class $modify(PlayerObject) { if (m_fields->isActuallyDart && Hacks::isHackEnabled("No Wave Trail")) return; PlayerObject::activateStreak(); } + void setRotation(float p0) { + if (Hacks::isHackEnabled("No Rotate")) return PlayerObject::setRotation(0); + PlayerObject::setRotation(p0); + } + void setVisible(bool p0) { + if (Hacks::isHackEnabled("Hide Player")) return PlayerObject::setVisible(false); + PlayerObject::setVisible(p0); + } }; diff --git a/src/Hacks/Quartz.cpp b/src/Hacks/Quartz.cpp index ac458d7..01a90c5 100644 --- a/src/Hacks/Quartz.cpp +++ b/src/Hacks/Quartz.cpp @@ -6,11 +6,8 @@ #include #include #include - // yes this code is messy, ill move it later - bool changedMacro = false; - bool SelectMacroUI::init(float _w, float _h, Dropdown* dropdown) { if (auto prismMenu = typeinfo_cast(CCScene::get()->getChildByID("prism-menu"))) { prismMenu->toggleVisibility(); @@ -363,6 +360,23 @@ CreateMacroUI* CreateMacroUI::create() { // sorry, too lazy to figure out how to get the class out QuartzMacro current_macro; +std::vector fixInputs(const std::vector& inputs) { + if (inputs.size() <= 1) { + return inputs; + } + + std::vector filteredInputs; + filteredInputs.push_back(inputs[0]); + + for (size_t i = 1; i < inputs.size(); ++i) { + if (inputs[i].down != inputs[i-1].down) { + filteredInputs.push_back(inputs[i]); + } + } + + return filteredInputs; +} + // could probably make a ctor but too lazy! PlayerFrame PlayerToFrame(PlayerObject* player, int frameNum, bool player2, bool isHolding, int buttonID) { PlayerFrame frame; @@ -425,6 +439,7 @@ class $modify(QuartzPlayLayer, PlayLayer) { int bot_frame = 0; int clicks = 0; int lastInputFrame = 0; + int previousFrame = 0; bool playLayerPostUpdate = false; int playLayerInit = 0; @@ -454,6 +469,8 @@ class $modify(QuartzPlayLayer, PlayLayer) { bool realHoldingP1 = false; bool realHoldingP2 = false; + bool changedInputP1 = false; + bool changedInputP2 = false; bool player2Visible = false; @@ -514,8 +531,10 @@ class $modify(QuartzPlayLayer, PlayLayer) { std::sort(current_macro.inputs.begin(), current_macro.inputs.end(), [](const QuartzInput& a, const QuartzInput& b) { return a.frame < b.frame; }); - if (!current_macro.inputs.empty()) + if (!current_macro.inputs.empty()) { + //current_macro.inputs = fixInputs(current_macro.inputs); m_fields->lastInputFrame = current_macro.inputs.back().frame; + } } } Hacks::setTPS(current_macro.framerate); @@ -643,6 +662,7 @@ class $modify(QuartzPlayLayer, PlayLayer) { if (input != current_macro.inputs.end()) { m_fields->holdingP1 = false; input->down = !input->down; + m_fields->changedInputP1 = input->down; log::debug("[P1] Change {} to {}", m_fields->bot_frame, input->down); GJBaseGameLayer::handleButton(input->down, input->button, true); RecreateInputState((input->down) ? 2 : 1, false, false); @@ -651,8 +671,7 @@ class $modify(QuartzPlayLayer, PlayLayer) { auto insertPos = std::find_if(current_macro.inputs.begin(), current_macro.inputs.end(), [bot_frame](const QuartzInput& input) { return input.frame > bot_frame && input.player2 == false; }); - - // Insert the new element at the desired position + m_fields->changedInputP1 = newInput.down; log::debug("[P1] Insert new frame at {}", m_fields->bot_frame); current_macro.inputs.insert(insertPos, newInput); GJBaseGameLayer::handleButton(newInput.down, newInput.button, true); @@ -697,6 +716,7 @@ class $modify(QuartzPlayLayer, PlayLayer) { if (input != current_macro.inputs.end()) { m_fields->holdingP2 = false; input->down = !input->down; + m_fields->changedInputP2 = input->down; log::debug("[P2] Change {} to {}", m_fields->bot_frame, input->down); GJBaseGameLayer::handleButton(input->down, input->button, false); RecreateInputState((input->down) ? 2 : 1, true, false); @@ -705,8 +725,7 @@ class $modify(QuartzPlayLayer, PlayLayer) { auto insertPos = std::find_if(current_macro.inputs.begin(), current_macro.inputs.end(), [bot_frame](const QuartzInput& input) { return input.frame > bot_frame && input.player2 == true; }); - - // Insert the new element at the desired position + m_fields->changedInputP2 = newInput.down; log::debug("[P2] Insert new frame at {}", m_fields->bot_frame); current_macro.inputs.insert(insertPos, newInput); GJBaseGameLayer::handleButton(newInput.down, newInput.button, false); @@ -744,14 +763,9 @@ class $modify(QuartzPlayLayer, PlayLayer) { void prevFrame(CCObject*) { if (m_fields->bot_frame <= 0 || !STOPTIME) return; -#ifdef GEODE_IS_WINDOWS m_fields->bot_frame -= 2; //m_unk1f8 m_gameState.m_currentProgress -= 2; -#else - m_fields->bot_frame -= 2; - m_gameState.m_currentProgress -= 2000; -#endif int bot_frame = m_fields->bot_frame; auto input_player = std::find_if(m_fields->player_frames.begin(), m_fields->player_frames.end(), [bot_frame](const PlayerFrame& input) { return input.frame == bot_frame && input.player2 == false; @@ -762,12 +776,20 @@ class $modify(QuartzPlayLayer, PlayLayer) { if (input_player != m_fields->player_frames.end() || input_player2 != m_fields->player_frames.end()) { if (input_player2 != m_fields->player_frames.end()) { UpdatePlayer(m_player2, *input_player2); - GJBaseGameLayer::handleButton(input_player2->isHolding, input_player2->buttonHold, true); + + m_fields->changedInputP2 = (m_fields->changedInputP2 != input_player2->isHolding); + if (m_fields->changedInputP2) { + GJBaseGameLayer::handleButton(input_player2->isHolding, input_player2->buttonHold, true); + } RecreateInputState((input_player2->isHolding) ? 2 : 1, true, false); } if (input_player != m_fields->player_frames.end()) { UpdatePlayer(m_player1, *input_player); - GJBaseGameLayer::handleButton(input_player->isHolding, input_player->buttonHold, false); + + m_fields->changedInputP1 = (m_fields->changedInputP1 != input_player->isHolding); + if (m_fields->changedInputP1) { + GJBaseGameLayer::handleButton(input_player->isHolding, input_player->buttonHold, false); + } RecreateInputState((input_player->isHolding) ? 2 : 1, true, false); } } @@ -777,7 +799,8 @@ class $modify(QuartzPlayLayer, PlayLayer) { log::debug("[-] Frame {}", m_fields->bot_frame); } void nextFrame(CCObject*) { - if (m_fields->bot_frame >= m_fields->lastInputFrame || !STOPTIME) return; + //if (m_fields->bot_frame >= m_fields->lastInputFrame || !STOPTIME) return; + if (!STOPTIME) return; /*int bot_frame = m_fields->bot_frame; auto input_player = std::find_if(m_fields->player_frames.begin(), m_fields->player_frames.end(), [bot_frame](const PlayerFrame& input) { return input.frame == bot_frame && input.player2 == false; @@ -808,7 +831,6 @@ class $modify(QuartzPlayLayer, PlayLayer) { GJBaseGameLayer::update(1.F / frameRate); } //STOPTIME = true;*/ - if (m_fields->bot_frame >= m_fields->lastInputFrame || !STOPTIME) return; int bot_frame = m_fields->bot_frame + 1; //std::cout << fmt::format("frame {} populated {}", bot_frame, m_fields->player_frames.size()) << std::endl; auto input_player = std::find_if(m_fields->player_frames.begin(), m_fields->player_frames.end(), [bot_frame](const PlayerFrame& input) { @@ -822,12 +844,18 @@ class $modify(QuartzPlayLayer, PlayLayer) { m_gameState.m_currentProgress = m_fields->bot_frame; if (input_player2 != m_fields->player_frames.end()) { UpdatePlayer(m_player2, *input_player2); - GJBaseGameLayer::handleButton(input_player2->isHolding, input_player2->buttonHold, true); + m_fields->changedInputP2 = (m_fields->changedInputP2 != input_player2->isHolding); + if (m_fields->changedInputP2) { + GJBaseGameLayer::handleButton(input_player2->isHolding, input_player2->buttonHold, true); + } RecreateInputState((input_player2->isHolding) ? 2 : 1, true, false); } if (input_player != m_fields->player_frames.end()) { UpdatePlayer(m_player1, *input_player); - GJBaseGameLayer::handleButton(input_player->isHolding, input_player->buttonHold, false); + m_fields->changedInputP1 = (m_fields->changedInputP1 != input_player->isHolding); + if (m_fields->changedInputP1) { + GJBaseGameLayer::handleButton(input_player->isHolding, input_player->buttonHold, false); + } RecreateInputState((input_player->isHolding) ? 2 : 1, true, false); } } @@ -874,6 +902,7 @@ class $modify(QuartzPlayLayer, PlayLayer) { void onQuit() { m_fields->bot_frame_dt = 0.F; m_fields->bot_frame = 0; + m_fields->previousFrame = 0; current_macro.loaf = 0.0F; current_macro.isEnabled = false; m_fields->playLayerPostUpdate = false; @@ -884,6 +913,7 @@ class $modify(QuartzPlayLayer, PlayLayer) { if (m_fields->checkpoints.size() == 0 || !m_isPracticeMode) { m_fields->bot_frame_dt = 0.F; m_fields->bot_frame = 0; + m_fields->previousFrame = 0; m_fields->checkpoints.clear(); RecreateInputState(1, false, false); RecreateInputState(1, true, false); @@ -913,6 +943,7 @@ class $modify(QuartzPlayLayer, PlayLayer) { current_macro.isEnabled = true; changedMacro = false; m_fields->bot_frame = 0; + m_fields->previousFrame = 0; PlayLayer::resetLevel(); if (Hacks::isHackEnabled("Record")) { current_macro.inputs = {}; @@ -1102,8 +1133,26 @@ class $modify(GJBaseGameLayer) { playLayer->m_fields->playLayerInit = agfvcbeaga; if (!!!(agfvcbeaga == playLayer->m_fields->playLayerInit)) return; - if (player1) GJBaseGameLayer::handleButton(input1->down, input1->button, !input1->player2); - if (player2) GJBaseGameLayer::handleButton(input2->down, input2->button, !input2->player2); + if (playLayer->m_fields->previousFrame != playLayer->m_fields->bot_frame) { + if (player1) { + playLayer->m_fields->changedInputP1 = (playLayer->m_fields->changedInputP1 != input1->down); + } + if (player2) { + playLayer->m_fields->changedInputP2 = (playLayer->m_fields->changedInputP2 != input2->down); + } + } + //if (player1) log::debug("ok {} - {} ({},{})", playLayer->m_fields->realChangedInputP1,input1->down, playLayer->m_fields->bot_frame,playLayer->m_fields->previousFrame); + if (player1) { + //log::info("updated"); + GJBaseGameLayer::handleButton(input1->down, input1->button, !input1->player2); + playLayer->m_fields->changedInputP1 = input1->down; + } + if (player2) { + GJBaseGameLayer::handleButton(input2->down, input2->button, !input2->player2); + playLayer->m_fields->changedInputP2 = input2->down; + } + + playLayer->m_fields->previousFrame = playLayer->m_fields->bot_frame; if (player1) playLayer->m_fields->player_frames.push_back(PlayerToFrame(m_player1, playLayer->m_fields->bot_frame, false, input1->down, input1->button)); //(m_player2 != nullptr && (m_player2->getPositionX() != 0 && m_player2->m_position.x != 0) if (playLayer->m_fields->player2Visible) { diff --git a/src/ImGui.cpp b/src/ImGui.cpp index f7dc87c..c8ebdf5 100644 --- a/src/ImGui.cpp +++ b/src/ImGui.cpp @@ -417,6 +417,9 @@ class $modify(MenuLayer) { if (name == "Menu-Style") { prismButton->showImGuiMenu = !prismButton->showImGuiMenu; } + if (name == "Language") { + Themes::LoadTheme(Themes::getCurrentTheme()); + } } // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) if (isSelected) diff --git a/src/Themes.cpp b/src/Themes.cpp index 584f9b1..867ab63 100644 --- a/src/Themes.cpp +++ b/src/Themes.cpp @@ -84,27 +84,44 @@ void Themes::UpdateOpacity(matjson::Object theme) { // other funcs void Themes::LoadTheme(matjson::Object theme) { - // Future Dark style by rewrking from ImThemes + auto lang = Hacks::getHack("Language"); + if (!Hacks::isHackEnabled("Live Theme Editing")) log::debug("Themes::LoadTheme - Start"); + ImVector ranges; ImGuiStyle& style = ImGui::GetStyle(); ImGuiIO& io = ImGui::GetIO(); - ImFontGlyphRangesBuilder builder; + if (lang != nullptr && lang->value.intValue != 0) { + // Future Dark style by rewrking from ImThemes + ImFontGlyphRangesBuilder builder; - // probably a bad idea to loop 127 times every frame, but this will only happen if the user has like "Live Theme Editing" enabled - // Add Czech character ranges manually - for (int i = 0x0100; i <= 0x017F; ++i) { // Czech characters in Unicode range - builder.AddChar(i); - } + // probably a bad idea to loop 127 times every frame, but this will only happen if the user has like "Live Theme Editing" enabled + // Add Czech character ranges manually + + if (!Hacks::isHackEnabled("Live Theme Editing")) log::debug("Themes::LoadTheme - Setup Builder"); - builder.AddRanges(io.Fonts->GetGlyphRangesCyrillic()); // russian chars - builder.AddRanges(io.Fonts->GetGlyphRangesVietnamese()); // vietnamese chars - //builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // JP chars - ImVector ranges; - builder.BuildRanges(&ranges); + for (int i = 0x0100; i <= 0x017F; ++i) { // Czech characters in Unicode range + builder.AddChar(i); + } + + if (!Hacks::isHackEnabled("Live Theme Editing")) log::debug("Themes::LoadTheme - Add Czech characters"); + + builder.AddRanges(io.Fonts->GetGlyphRangesCyrillic()); // russian chars + + if (!Hacks::isHackEnabled("Live Theme Editing")) log::debug("Themes::LoadTheme - Add Cyrillic characters"); + builder.AddRanges(io.Fonts->GetGlyphRangesVietnamese()); // vietnamese chars + if (!Hacks::isHackEnabled("Live Theme Editing")) log::debug("Themes::LoadTheme - Add Vietnamese characters"); + //builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // JP chars + if (!Hacks::isHackEnabled("Live Theme Editing")) log::debug("Themes::LoadTheme - Add Japanese characters"); + builder.BuildRanges(&ranges); + if (!Hacks::isHackEnabled("Live Theme Editing")) log::debug("Themes::LoadTheme - Build ranges"); + } std::string fontName = (Mod::get()->getResourcesDir() / "PrismMenu.otf").string(); //std::string fontName = (Mod::get()->getResourcesDir() / "Hack-Regular.ttf").string(); float menuScale = Hacks::getHack("Menu Scale")->value.floatValue; + io.Fonts->AddFontFromFileTTF(fontName.c_str(), theme["FontSize"].as_int() * menuScale, NULL, ranges.Data); + if (!Hacks::isHackEnabled("Live Theme Editing")) log::debug("Themes::LoadTheme - Add FontSize TTF"); io.Fonts->AddFontFromFileTTF(fontName.c_str(), theme["IconSize"].as_int() * menuScale, NULL, ranges.Data); + if (!Hacks::isHackEnabled("Live Theme Editing")) log::debug("Themes::LoadTheme - Add IconSize TTF"); style.Alpha = 1.0f; style.DisabledAlpha = 1.0f; @@ -201,6 +218,7 @@ void Themes::LoadTheme(matjson::Object theme) { "TableRowBgAlt": [25, 27, 31, 128], "TextSelectedBg": [60, 55, 152, 255] */ + if (!Hacks::isHackEnabled("Live Theme Editing")) log::debug("Themes::LoadTheme - Loaded Theme!"); } #endif diff --git a/src/UI/PrismUI.cpp b/src/UI/PrismUI.cpp index 0069d9c..b67cd07 100644 --- a/src/UI/PrismUI.cpp +++ b/src/UI/PrismUI.cpp @@ -442,55 +442,59 @@ void PrismUIButton::onBtn(CCObject* ret) { geode::FileSetting::Filter filter; filter.description = "Theme (*.json)"; filter.files.insert("*.json"); - FLAlertLayer::create("Error", "Please wait until a future update for this to be fixed.", "OK")->show(); -#if 0 - file::pickFile( - file::PickMode::OpenFile, - { - dirs::getGameDir(), - { filter } - }, - [&](std::filesystem::path path) { - auto saveDir = Mod::get()->getSaveDir().string(); - if (!std::filesystem::exists(saveDir + "/themes")) { - std::filesystem::create_directory(saveDir + "/themes"); - } - auto savePath = saveDir + "/themes/" + path.filename().string(); - if (std::filesystem::exists(savePath)) { - std::filesystem::remove(savePath); + + m_listener.bind([] (FileEvent::Event* e) { + if (e->getValue()) { + if (e->getValue()->isOk()) { + auto path = e->getValue()->unwrap(); + auto saveDir = Mod::get()->getSaveDir().string(); + if (!std::filesystem::exists(saveDir + "/themes")) { + std::filesystem::create_directory(saveDir + "/themes"); + } + auto savePath = saveDir + "/themes/" + path.filename().string(); + if (std::filesystem::exists(savePath)) { + std::filesystem::remove(savePath); + } + std::filesystem::copy_file(path, savePath); // why this crashes if a file already exists? idk + FLAlertLayer::create("Success!", "The theme has successfully been imported! Restart your game to use it.", "OK")->show(); + } else { + log::error("Something went wrong when picking files: {}", e->getValue()->err()); } - std::filesystem::copy_file(path, savePath); // why this crashes if a file already exists? idk - FLAlertLayer::create("Success!", "The theme has successfully been imported! Restart your game to use it.", "OK")->show(); + } else { + log::error("Something went wrong when picking files: Value is empty."); } - ); -#endif + }); + + m_listener.setFilter(file::pick(file::PickMode::OpenFile, { dirs::getGameDir(), { filter }})); + } else if (name == "Import Macro") { geode::FileSetting::Filter filter; filter.description = "Macro (*.gdr)"; filter.files.insert("*.gdr.json"); filter.files.insert("*.gdr"); - FLAlertLayer::create("Error", "Please wait until a future update for this to be fixed.", "OK")->show(); -#if 0 - file::pickFile( - file::PickMode::OpenFile, - { - dirs::getGameDir(), - { filter } - }, - [&](std::filesystem::path path) { - auto saveDir = Mod::get()->getSaveDir().string(); - if (!std::filesystem::exists(saveDir + "/macros")) { - std::filesystem::create_directory(saveDir + "/macros"); - } - auto savePath = saveDir + "/macros/" + path.filename().string(); - if (std::filesystem::exists(savePath)) { - std::filesystem::remove(savePath); + + m_listener.bind([] (FileEvent::Event* e) { + if (e->getValue()) { + if (e->getValue()->isOk()) { + auto path = e->getValue()->unwrap(); + auto saveDir = Mod::get()->getSaveDir().string(); + if (!std::filesystem::exists(saveDir + "/macros")) { + std::filesystem::create_directory(saveDir + "/macros"); + } + auto savePath = saveDir + "/macros/" + path.filename().string(); + if (std::filesystem::exists(savePath)) { + std::filesystem::remove(savePath); + } + std::filesystem::copy_file(path, savePath); // why this crashes if a file already exists? idk + FLAlertLayer::create("Success!", "The macro has successfully been imported!", "OK")->show(); + } else { + log::error("Something went wrong when picking files: {}", e->getValue()->err()); } - std::filesystem::copy_file(path, savePath); // why this crashes if a file already exists? idk - FLAlertLayer::create("Success!", "The macro has successfully been imported!", "OK")->show(); + } else { + log::error("Something went wrong when picking files: Value is empty."); } - ); -#endif + }); + m_listener.setFilter(file::pick(file::PickMode::OpenFile, { dirs::getGameDir(), { filter }})); } else if (name == "Reset Speedhack") { HackItem* speedHack = Hacks::getHack("Speedhack"); speedHack->value.floatValue = 1.0F; diff --git a/src/UI/PrismUI.hpp b/src/UI/PrismUI.hpp index 80baafe..4a8d724 100644 --- a/src/UI/PrismUI.hpp +++ b/src/UI/PrismUI.hpp @@ -1,6 +1,7 @@ #pragma once #include #include "../Misc/DownloadManager.hpp" +#include #include #include #include "../Languages.hpp" @@ -8,8 +9,11 @@ using namespace geode::prelude; +using FileEvent = Task>; + class PrismUIButton : public CCNode, public TextInputDelegate, public CCKeyboardDelegate { protected: + EventListener m_listener; CCMenu* menu; HackItem* m_hack; Slider* m_slider; diff --git a/src/hacks.hpp b/src/hacks.hpp index 55c6003..15254d7 100644 --- a/src/hacks.hpp +++ b/src/hacks.hpp @@ -108,6 +108,7 @@ class Hacks { "Jump Hack", "Layout Mode", "Show Hidden Objects", + "Hide Level", "Change Gravity", "Force Platformer Mode", "No Mirror Transition", diff --git a/src/main.cpp b/src/main.cpp index 3434bfd..7bf574e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,6 +20,7 @@ using namespace geode::prelude; #include +#include /* for i in range(char2nr('A'), char2nr('Z')) @@ -29,9 +30,29 @@ endfor PrismButton* prismButton; bool firstLoad = false; +bool removeMe = false; + +class $modify(GameManager) { + void reloadAll(bool switchingModes, bool toFullscreen, bool borderless, bool unused) { + if (prismButton != nullptr) { + SceneManager::get()->forget(prismButton); + // yeah this seems safe, definitely wont be a problem in the future + delete prismButton; + //prismButton->release(); + } + GameManager::reloadAll(switchingModes, toFullscreen, borderless, unused); + removeMe = true; + } +}; + class $modify(MenuLayer) { bool init() { if (!MenuLayer::init()) return false; + if (removeMe) { + firstLoad = false; + removeMe = false; + } + if (firstLoad) return true; HackItem* posX = Hacks::getHack("Button Position X"); HackItem* posY = Hacks::getHack("Button Position Y"); @@ -40,6 +61,7 @@ class $modify(MenuLayer) { #ifndef GEODE_IS_MACOS prismButton = PrismButton::create(CCScene::get()); prismButton->setVisible(Hacks::isHackEnabled("Show Button")); + if (Mod::get()->getSettingValue("hide-button")) prismButton->setVisible(false); prismButton->setID("prism-icon"); SceneManager::get()->keepAcrossScenes(prismButton); #endif @@ -171,14 +193,16 @@ class $modify(CCKeyboardDispatcher) { class $modify(PauseLayer) { void customSetup() { PauseLayer::customSetup(); - for (size_t i = 0; i < this->getChildrenCount(); i++) { - auto obj = this->getChildren()->objectAtIndex(i); - if (Utils::getNodeName(obj) == "cocos2d::CCMenu") { - auto menu = static_cast(obj); - auto button = PrismButton::createButton(this); - button->setPositionX(-240); - menu->addChild(button); - break; + if (!Mod::get()->getSettingValue("hide-button")) { + for (size_t i = 0; i < this->getChildrenCount(); i++) { + auto obj = this->getChildren()->objectAtIndex(i); + if (Utils::getNodeName(obj) == "cocos2d::CCMenu") { + auto menu = static_cast(obj); + auto button = PrismButton::createButton(this); + button->setPositionX(-240); + menu->addChild(button); + break; + } } } @@ -375,7 +399,7 @@ class $modify(PrismPlayLayer, PlayLayer) { m_fields->accuracyLabel->setPosition({36, winSize.height - 35}); m_fields->accuracyLabel->setScale(0.5F); m_fields->accuracyLabel->setOpacity(255 / 2); - m_fields->accuracyLabel->setVisible(Hacks::isHackEnabled("Noclip Accuracy")); + m_fields->accuracyLabel->setVisible(Hacks::isHackEnabled("Noclip Accuracy") && (Hacks::isHackEnabled("Noclip") || Hacks::isHackEnabled("No Solids") || Hacks::isHackEnabled("No Spikes"))); m_fields->accuracyLabel->setAlignment(CCTextAlignment::kCCTextAlignmentLeft); m_fields->accuracyLabel->setZOrder(1000); m_fields->accuracyLabel->setTag(10420); // prevent PlayLayer from interfering @@ -408,7 +432,7 @@ class $modify(PrismPlayLayer, PlayLayer) { if (m_fields->accuracyLabel != nullptr) { float accuracy = ((static_cast(m_gameState.m_currentProgress - m_fields->death)) / static_cast(m_gameState.m_currentProgress)) * 100; // for some reason this doesnt work on android, like it goes in the negatives m_fields->accuracyLabel->setString(fmt::format("{}%", Utils::setPrecision(accuracy, 2)).c_str()); - m_fields->accuracyLabel->setVisible(Hacks::isHackEnabled("Noclip Accuracy")); + m_fields->accuracyLabel->setVisible(Hacks::isHackEnabled("Noclip Accuracy") && (Hacks::isHackEnabled("Noclip") || Hacks::isHackEnabled("No Solids") || Hacks::isHackEnabled("No Spikes"))); if (m_gameState.m_currentProgress % 4 == 0) { // quarter step m_fields->accuracyLabel->setColor({255,255,255}); if (m_fields->flashOpacity > 1.0F) {