diff --git a/.gitignore b/.gitignore index d8108ef..b57a114 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ build-linux/ -build-android/ -build-armv8/ +build-android*/ test/build-linux test/compile_commands.json .cache/ diff --git a/.gitmodules b/.gitmodules index 881f23f..893dce2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "libs/pl_mpeg"] +[submodule "libs/pl_mpeg"] path = libs/pl_mpeg url = https://github.com/phoboslab/pl_mpeg -[submodule "libs/discord-rpc"] - path = libs/discord-rpc - url = https://github.com/discord/discord-rpc diff --git a/.vscode/launch.json b/.vscode/launch.json index f43b325..a68e325 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,11 +1,8 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { - "name": "(Windows) Launch", + "name": "Launch GD (Debug)", "type": "cppvsdbg", "request": "launch", "program": "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Geometry Dash\\GeometryDash.exe", @@ -13,7 +10,21 @@ "stopAtEntry": false, "cwd": "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Geometry Dash\\", "environment": [], - "console": "internalConsole" + "console": "internalConsole", + "symbolSearchPath": "${workspaceFolder}\\build", + "sourceFileMap": { + "C:/Users/proga/Desktop/Codes/Geode projets/GDUtils-Geode": "${workspaceFolder}" + } + }, + { + "name": "Attach to GD", + "type": "cppvsdbg", + "request": "attach", + "processId": "${command:pickProcess}", + "symbolSearchPath": "${workspaceFolder}\\build", + "sourceFileMap": { + "C:/Users/proga/Desktop/Codes/Geode projets/GDUtils-Geode": "${workspaceFolder}" + } } ] -} \ No newline at end of file +} diff --git a/CMakeLists.txt b/CMakeLists.txt index aecf372..1ea23b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,39 +14,10 @@ endif() set(CMAKE_CXX_VISIBILITY_PRESET hidden) include(cmake/CPM.cmake) -if(NOT DEFINED GEODE_TARGET_PLATFORM) - set(GEODE_TARGET_PLATFORM "Win64") - set(GEODE_GD_VERSION 2.2074) - set(GEODE_COMP_GD_VERSION 22074) -endif() - -if (${GEODE_TARGET_PLATFORM} STREQUAL "Win64") - set(GEODE_COMPILER "clang-cl") - set(GEODE_CCACHE_VARIANT "sccache") - #set(GEODE_TRIPLE "x86_64-unknown-windows-msvc") - if(WIN32) # force it! - set(CMAKE_SYSTEM_PROCESSOR x86_64) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64") - endif() -endif() - set(PROJECT_NAME GDUtils) project(${PROJECT_NAME} VERSION 1.0.0) -# Use GLOB_RECURSE instead of GLOB -# to recursively add all source files -# under src/ -file(GLOB SOURCES - src/*.cpp - src/MoreLeaderboards/*.cpp - src/Notifications/*.cpp - src/Secret/*.cpp - src/Settings/*.cpp - src/Utils/*.cpp - src/Styles/*.cpp - include/*.cpp -) +file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.cpp) # Set up the mod binary add_library(${PROJECT_NAME} SHARED ${SOURCES}) @@ -60,19 +31,24 @@ set(BUILD_TOOLS_DOCS OFF) #set(INSTALL_STATIC_LIBS OFF) CPMAddPackage("gh:alanxz/rabbitmq-c#035eaa8") +if (WIN32) + target_compile_options(rabbitmq-static PRIVATE -Wno-incompatible-pointer-types) +endif() + set(BUILD_TESTING OFF) set(BUILD_BENCH OFF) set(BUILD_SHARED_LIBS OFF) #CPMAddPackage("gh:libuv/libuv#c1a9f01") #CPMAddPackage("gh:CopernicaMarketingSoftware/AMQP-CPP#ca49382") - +CPMAddPackage("gh:camila314/uibuilder#main") # i love it target_include_directories(${PROJECT_NAME} PRIVATE libs/filesystem libs/pl_mpeg/ libs/glew/ ${rabbitmq-c_SOURCE_DIR}/include + src/ #${amqpcpp_SOURCE_DIR}/src #${amqpcpp_SOURCE_DIR}/include #${libuv_SOURCE_DIR}/include @@ -87,10 +63,10 @@ endif() add_subdirectory($ENV{GEODE_SDK} ${CMAKE_CURRENT_BINARY_DIR}/geode) if (APPLE AND NOT (${CMAKE_SYSTEM_NAME} STREQUAL "iOS" OR IOS)) - target_link_libraries(${PROJECT_NAME} rabbitmq::rabbitmq-static "-framework OpenGL") + target_link_libraries(${PROJECT_NAME} UIBuilder rabbitmq::rabbitmq-static "-framework OpenGL") #target_link_libraries(${PROJECT_NAME} uv_a amqpcpp "-framework OpenGL") else() - target_link_libraries(${PROJECT_NAME} rabbitmq::rabbitmq-static) + target_link_libraries(${PROJECT_NAME} UIBuilder rabbitmq::rabbitmq-static) #target_link_libraries(${PROJECT_NAME} uv_a amqpcpp) endif() if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" AND WIN32) diff --git a/README.md b/README.md index 2dd1a48..02349f7 100644 --- a/README.md +++ b/README.md @@ -92,11 +92,28 @@ EventData data = { GDUtils::Events::RateEvent::emit(data); ``` -### Example Code (Listening for notification events from GDUtils) +### Example Code (Listening for notification events from GDUtils, and checking if the server is online) ```cpp $execute { - new EventListener>(+[](GDUtils::Events::OnRate* e) { - log::info("A rate event with the title {}", e->getTitle()); // A rate event with the title Small Daily Chest available! + // Listening for *any* rate event. + GDUtils::Events::OnRate().listen([](EventData const& e) { + log::info("A rate event with the title {}", e.getTitle()); // A rate event with the title Small Daily Chest available! + return ListenerResult::Propagate; + }); + + // Listening for rate events, filtering only by daily + GDUtils::Events::OnRate(EventType::Daily).listen([](EventData const& e) { + log::info("A daily event with the level name {}", e.getLevelName()); // A daily event with the level name Cycles + return ListenerResult::Propagate; + }); + + // Checking when we connected. + GDUtils::Events::OnServerConnect().listen([](bool const& connected) { + Loader::get()->queueInMainThread([connected]() { + if (connected) { + log::info("I am connected to the notifiaction servers!"); + } + }); return ListenerResult::Propagate; }); } @@ -105,7 +122,7 @@ View the `test` directory if you want to view an example mod using the API. ## Libraries Used - [Geode](https://github.com/geode-sdk/geode) -- [socket.io-client-cpp](https://github.com/socketio/socket.io-client-cpp) +- [rabbitmq-c](https://github.com/alanxz/rabbitmq-c) - [pl_mpeg](https://github.com/phoboslab/pl_mpeg) ## Credits diff --git a/about.md b/about.md index 1c61fc7..5216488 100644 --- a/about.md +++ b/about.md @@ -2,7 +2,7 @@ **by [Jouca](user:7026949) and [Firee](user:6253758)** A Geometry Dash Mod for adding more tools such as Notifications, auto-song mute, game fixes & more! -![Mod Example](gdutilsdevs.gdutils/Screenshot_1.png&scale:0.8) +![Mod Example](gdutilsdevs.gdutils/Screenshot_1.png?scale:0.8) # Need help? * You can join our [Discord server](https://discord.gg/MU4Rpc6xbJ) for **any assistance** or about **next updates**, **sneak peeks** & **more**! diff --git a/changelog.md b/changelog.md index 7164f95..80c1390 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,44 @@ # Changelog -## v... (---) +## v1.6.0 (2026-08-03) +* GDUtils ported & rewritten for Geode v5 (GD 2.2081) +* Added 2025 GD Awards badge. +* Changed logic for chest notifications. +* Changed locations for where GDUtils stores files. +* Adjusted default parameters for the demon list to be AreDL +* Updated UL staff badges textures. * Fixed Spotify feature not unmuting when playtesting in Editor. +* Fixed notification being clickable. +* Fixed chests crashing upon opening for Android. +* Fixed daily chests being ignore on claiming. +* Fixed GDUtils badges crashing when clicking to view details. +* Fixed daily chests crashing. +* Fixed AreDL demon placement not working. +* Fixed notifications queue potentially staying open if the connection didn't close properly. + +## v1.6.0-beta.5 (2026-06-30) +* Adjusted default parameters for the demon list to be AreDL +* Fixed AreDL demon placement not working. + +## v1.6.0-beta.4 (2026-05-13) +* Added 2025 GD Awards badge. +* Fixed daily chests crashing. + +## v1.6.0-beta.3 (2026-04-24) +* Added back leaderboards & moderator list. +* Added back custom backgrounds. +* Fixed daily chests being ignore on claiming. +* Fixed GDUtils badges crashing when clicking to view details. + +## v1.6.0-beta.2 (2026-03-08) +* Fixed chests crashing upon opening for Android. + +## v1.6.0-beta.1 (2026-03-08) +* GDUtils ported to Geode 5.0.0 (GD 2.2081) +* Changed logic for chest notifications. +* Changed locations for where GDUtils stores files. +* Temporarily removed leaderboards due to not being rewritten yet. +* Fixed Spotify feature not unmuting when playtesting in Editor. +* Fixed notification being clickable. ## v1.5.4 (2025-09-09) * Added coloured container animation when searching a friend on the friend list. diff --git a/include/RateEvent.hpp b/include/RateEvent.hpp index e314872..20446ec 100644 --- a/include/RateEvent.hpp +++ b/include/RateEvent.hpp @@ -4,75 +4,17 @@ #include "Types.hpp" namespace GDUtils::Events { - class RateEvent : public geode::Event { - protected: - EventData m_eventData; + class RateEvent : public geode::Event { public: - RateEvent(EventData data) : m_eventData(data) {}; - - EventType getEventType() const { return m_eventData.type; }; - std::string getLevelName() const { return m_eventData.level_name; }; - int getLevelID() const { return m_eventData.level_id; }; + using Event::Event; static void emit(EventData data) { - RateEvent(data).post(); + RateEvent().send(data); }; - EventData getData() const { return m_eventData; }; - static EventType intToType(int type) { - switch (type) { - default: - return EventType::NA; - case 0: // Rate - return EventType::Rate; - case 1: // Daily - return EventType::Daily; - case 2: // Weekly - return EventType::Weekly; - case 3: // Small chest - return EventType::smallChest; - case 4: // Large chest - return EventType::largeChest; - case 5: // List - return EventType::List; - case 6: // Event - return EventType::Event; - case 7: // Announcement - return EventType::Announcement; - } - } - static int typeToInt(EventType type) { - switch (type) { - case EventType::NA: - return -1; - case EventType::Rate: // Rate - return 0; - case EventType::Daily: // Daily - return 1; - case EventType::Weekly: // Weekly - return 2; - case EventType::smallChest: // Small chest - return 3; - case EventType::largeChest: // Large chest - return 4; - case EventType::List: // List - return 5; - case EventType::Event: // Event - return 6; - case EventType::Announcement: // Announcement - return 7; - } - } }; - - class OnRate : public geode::Event { - protected: - EventData m_eventData; - public: - OnRate(EventData data) : m_eventData(data) {}; - - std::string getTitle() const { return m_eventData.title; }; - EventType getEventType() const { return m_eventData.type; }; - std::string getLevelName() const { return m_eventData.level_name; }; - int getLevelID() const { return m_eventData.level_id; }; - EventData getData() const { return m_eventData; }; + struct OnRate final : geode::GlobalEvent { + using GlobalEvent::GlobalEvent; + }; + struct OnServerConnect final : geode::ThreadSafeEvent { + using ThreadSafeEvent::ThreadSafeEvent; }; } diff --git a/include/Types.hpp b/include/Types.hpp index f810ae9..f8213ca 100644 --- a/include/Types.hpp +++ b/include/Types.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include "RateEvent.hpp" enum EventType { Rate, Daily, @@ -28,6 +29,54 @@ struct EventData { int level_id = -1; std::string levels_list; int maxToCompleteList = 0; + std::string getTitle() const { return title; }; + EventType getEventType() const { return type; }; + std::string getLevelName() const { return level_name; }; + int getLevelID() const { return level_id; }; + int typeToInt() const { + switch (type) { + case EventType::NA: + return -1; + case EventType::Rate: // Rate + return 0; + case EventType::Daily: // Daily + return 1; + case EventType::Weekly: // Weekly + return 2; + case EventType::smallChest: // Small chest + return 3; + case EventType::largeChest: // Large chest + return 4; + case EventType::List: // List + return 5; + case EventType::Event: // Event + return 6; + case EventType::Announcement: // Announcement + return 7; + } + } + EventType intToType(int intType) const { + switch (intType) { + default: + return EventType::NA; + case 0: // Rate + return EventType::Rate; + case 1: // Daily + return EventType::Daily; + case 2: // Weekly + return EventType::Weekly; + case 3: // Small chest + return EventType::smallChest; + case 4: // Large chest + return EventType::largeChest; + case 5: // List + return EventType::List; + case 6: // Event + return EventType::Event; + case 7: // Announcement + return EventType::Announcement; + } + } }; template<> @@ -110,4 +159,23 @@ struct matjson::Serialize { } return geode::Ok(data); } + static matjson::Value toJson(EventData const& value) { + auto val = Value::object(); + val.set("demon", value.demon); + val.set("starsum", value.starsum); + val.set("starsum", value.starsum); + val.set("stars", value.stars); + val.set("rate", value.rate); + val.set("type", value.typeToInt()); + val.set("title", value.title); + val.set("level_name", value.level_name); + val.set("level_creator", value.level_creator); + val.set("coins", value.coins); + val.set("verified_coins", value.verified_coins); + val.set("platformer", value.platformer); + val.set("level_id", value.level_id); + val.set("levels_list", value.levels_list); + val.set("maxToCompleteList", value.maxToCompleteList); + return val; + } }; diff --git a/libs/discord-rpc b/libs/discord-rpc deleted file mode 160000 index 963aa9f..0000000 --- a/libs/discord-rpc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 963aa9f3e5ce81a4682c6ca3d136cddda614db33 diff --git a/libs/link-libs/discord-rpc/discord-rpc.lib b/libs/link-libs/discord-rpc/discord-rpc.lib deleted file mode 100644 index 99ac434..0000000 Binary files a/libs/link-libs/discord-rpc/discord-rpc.lib and /dev/null differ diff --git a/libs/link-libs/discord-rpc/libdiscord-rpc.a b/libs/link-libs/discord-rpc/libdiscord-rpc.a deleted file mode 100644 index c83261f..0000000 Binary files a/libs/link-libs/discord-rpc/libdiscord-rpc.a and /dev/null differ diff --git a/mod.json b/mod.json index b915767..f4170f8 100644 --- a/mod.json +++ b/mod.json @@ -1,11 +1,11 @@ { - "geode": "4.9.0", - "version": "v1.5.4", + "geode": "5.8.2", + "version": "v1.6.0", "gd": { - "win": "2.2074", - "mac": "2.2074", - "android": "2.2074", - "ios": "2.2074" + "win": "2.2081", + "mac": "2.2081", + "android": "2.2081", + "ios": "2.2081" }, "id": "gdutilsdevs.gdutils", "name": "GDUtils", @@ -16,8 +16,8 @@ "source": "https://github.com/Jouca/GDUtils-Geode" }, "dependencies": { - "geode.node-ids": ">=v1.21.1", - "jouca.badgesapi": ">=v1.2.4" + "geode.node-ids": ">=v1.23.3", + "jouca.badgesapi": ">=v1.5.0" }, "api": { "include": [ "include/*.hpp" ] @@ -31,7 +31,8 @@ ], "resources": { "files": [ - "resources/gauntlets/*.png" + "resources/gauntlets/*.png", + "resources/gauntlets/particles.json" ], "sprites": [ "resources/*.png" @@ -267,11 +268,18 @@ "description": "This category is for any other feature for GDUtils.\nYou can choose whether to enable or disable some options if you do not want them.", "type": "title" }, + "clickableBadges": { + "name": "Clickable Badges", + "description": "Makes badges in Profile's clickable, showing more information about them.", + "type": "bool", + "default": true + }, "customBadges": { "name": "Custom Badges", "description": "Whether or not to show custom badges in Profile and Comments.", "type": "bool", - "default": true + "default": true, + "enable-if": "clickableBadges" }, "friendSearch": { "name": "Search Friends", @@ -289,21 +297,9 @@ "name": "Demon List Selection", "description": "Whether or not to select between Pointercrate or AreDL for placements.", "type": "string", - "default": "Pointercrate", + "default": "AreDL", "one-of": ["Pointercrate", "AreDL"] }, - "levelsProtocol": { - "name": "Allow Levels Protocol", - "description": "Whether or not to allow Geometry Dash to redirect to a level if you were to use a https://gdutils.com/ url, or gdutils: protocol.", - "type": "bool", - "default": true - }, - "levelsProtocolButton": { - "name": "Share level URL Button", - "description": "Whether or not to show the Share Level URL button in the Level Info Menu.", - "type": "bool", - "default": true - }, "socketServer": { "name": "Notifications Server", "description": "Allows you to receive rate notifications. (Recommended to keep enabled)\n\nRestart the game to apply changes.", diff --git a/resources/badges/gdAwards2025Badge.png b/resources/badges/gdAwards2025Badge.png new file mode 100644 index 0000000..e47926f Binary files /dev/null and b/resources/badges/gdAwards2025Badge.png differ diff --git a/resources/badges/ul_dev_badge.png b/resources/badges/ul_dev_badge.png index 600a7e0..55d3667 100644 Binary files a/resources/badges/ul_dev_badge.png and b/resources/badges/ul_dev_badge.png differ diff --git a/resources/badges/ul_helper_badge.png b/resources/badges/ul_helper_badge.png index 9917bb5..38b1851 100644 Binary files a/resources/badges/ul_helper_badge.png and b/resources/badges/ul_helper_badge.png differ diff --git a/resources/badges/ul_officer_badge.png b/resources/badges/ul_officer_badge.png index 8cac234..a87eedc 100644 Binary files a/resources/badges/ul_officer_badge.png and b/resources/badges/ul_officer_badge.png differ diff --git a/resources/badges/ul_trainee_badge.png b/resources/badges/ul_trainee_badge.png index 945ec6a..3c2ca76 100644 Binary files a/resources/badges/ul_trainee_badge.png and b/resources/badges/ul_trainee_badge.png differ diff --git a/resources/gauntlets/particles.json b/resources/gauntlets/particles.json new file mode 100644 index 0000000..3bebcdb --- /dev/null +++ b/resources/gauntlets/particles.json @@ -0,0 +1,228 @@ +{ + "World": { + "background": { "sprite": "world_gauntlet.png", "scale": 1.27 }, + "gauntlet": { "position": [1.0, 16.0], "scale": 1.0, "zOrder": 3 }, + "particles": [ + { "string": "22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.729412a0a0.352941a0a0.796078a0a1a0a7a0a0a0a0.729412a0a0.352941a0a0.796078a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [10.0, 24.0], "scale": [1.31, 2.61] }, + { "string": "22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.34902a0a0.466667a0a0.792157a0a1a0a7a0a0a0a0.34902a0a0.466667a0a0.792157a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [6.0, 24.0], "scale": [1.31, 2.61] }, + { "string": "22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.360784a0a0.854902a0a0.368627a0a1a0a7a0a0a0a0.360784a0a0.854902a0a0.368627a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [2.0, 24.0], "scale": [1.31, 2.61] }, + { "string": "22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.866667a0a0.839216a0a0.247059a0a1a0a7a0a0a0a0.866667a0a0.839216a0a0.247059a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [-2.0, 24.0], "scale": [1.31, 2.61] }, + { "string": "22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.866667a0a0.294118a0a0.247059a0a1a0a7a0a0a0a0.866667a0a0.294118a0a0.247059a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [-6.0, 24.0], "scale": [1.31, 2.61] }, + { "string": "22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.729412a0a0.352941a0a0.796078a0a1a0a7a0a0a0a0.729412a0a0.352941a0a0.796078a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [-9.0, 24.0], "scale": [-1.31, 2.61] }, + { "string": "22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.34902a0a0.466667a0a0.792157a0a1a0a7a0a0a0a0.34902a0a0.466667a0a0.792157a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [-5.0, 24.0], "scale": [-1.31, 2.61] }, + { "string": "22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.360784a0a0.854902a0a0.368627a0a1a0a7a0a0a0a0.360784a0a0.854902a0a0.368627a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [-1.0, 24.0], "scale": [-1.31, 2.61] }, + { "string": "22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.866667a0a0.839216a0a0.247059a0a1a0a7a0a0a0a0.866667a0a0.839216a0a0.247059a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [3.0, 24.0], "scale": [-1.31, 2.61] }, + { "string": "22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.866667a0a0.294118a0a0.247059a0a1a0a7a0a0a0a0.866667a0a0.294118a0a0.247059a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [7.0, 24.0], "scale": [-1.31, 2.61] }, + { "string": "38a-1a1.5a0.3a21a90a90a0a0a31a69a0a0a0a0a0a0a2a1a65a57a1a0a1a0a1a0a1a0a5a1a0a0a1a0a1a0a1a0a1a0a0.2a0a0.4a0a0a0a0a0a0a0a0a2a1a0a0a0a169a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [1.0, 6.0], "scale": [1.71, 1.66] }, + { "string": "11a-1a1.5a0.3a6a90a90a0a0a31a69a0a0a0a0a0a0a4a1a0a0a1a0a1a0a1a0a1a0a7a1a52a55a1a0a1a0a1a0a1a0a0.2a0a0.4a0a0a0a0a0a0a0a0a2a1a0a0a0a167a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [1.0, 16.0], "scale": [1.835, 1.485] } + ] + }, + "Fantasy": { + "background": { "sprite": "fantasy_gauntlet.png", "scale": 1.225 }, + "gauntlet": { "position": [-2.0, 14.0], "scale": 0.925, "zOrder": 2 }, + "particles": [ + { "string": "26a-1a5a0.3a4a-90a14a9a0a17a0a0a0a0a0a0a0a2a1a76a325a0.537255a0a0.898039a0a0.164706a0a1a0a2a1a148a149a0.537255a0a0.898039a0a0.164706a0a1a0a0a0a0.3a0a0a0a0a0a0a0a0a2a0a0a0a0a146a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [-2.0, 103.0], "scale": [2.88, 4.603] } + ] + }, + "Portal": { + "background": { "sprite": "portal_gauntlet.png", "scale": 1.225 }, + "gauntlet": { "position": [-2.0, 14.0], "scale": 0.925, "zOrder": 2 }, + "particles": [ + { "string": "13a-1a1a0.3a10a90a90a29a0a11a0a0a0a0a0a0a0a50a1a0a37a0.376471a0a0.109804a0a0.243137a0a1a0a32a1a142a96a0.376471a0a0.109804a0a0.243137a0a1a0a0.5a0a0.3a0a0a0a0a0a0a0a1a2a1a0a0a0a190a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [2.88, 3.978] }, + { "string": "13a-1a1a0.3a10a90a90a29a0a11a0a0a0a0a0a0a0a50a1a0a37a0.0705882a0a0.172549a0a0.203922a0a1a0a32a1a142a96a0.0705882a0a0.172549a0a0.203922a0a1a0a0.5a0a0.3a0a0a0a0a0a0a0a1a2a1a0a0a0a190a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [2.88, 3.978] }, + { "string": "38a-1a2a0.3a16a90a180a29a0a11a0a0a0a0a0a0a0a6a1a0a0a0.760784a0a0.380392a0a0.835294a0a1a0a3a1a0a0a0.760784a0a0.380392a0a0.835294a0a1a0a0.18a0a0.49a0a43a0a33a0a-34a0a1a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.03, 1.03] }, + { "string": "38a-1a2a0.3a16a90a180a29a0a11a0a0a0a0a0a0a0a6a1a0a0a0.376471a0a0.690196a0a0.831373a0a1a0a3a1a0a0a0.376471a0a0.690196a0a0.831373a0a1a0a0.18a0a0.49a0a43a0a33a0a-34a0a1a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.155, 1.355] }, + { "string": "30a-1a1a0.3a30a90a180a29a0a11a0a0a0a0a0a0a0a4a1a0a0a0.760784a0a0.380392a0a0.835294a0a1a0a2a1a0a0a0.760784a0a0.380392a0a0.835294a0a1a0a0.18a0a0.49a0a43a0a33a0a-41a0a1a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.455, 1.655] }, + { "string": "30a-1a1a0.3a30a90a180a29a0a11a0a0a0a0a0a0a0a4a1a0a0a0.376471a0a0.690196a0a0.831373a0a1a0a2a1a0a0a0.376471a0a0.690196a0a0.831373a0a1a0a0.18a0a0.49a0a43a0a33a0a-41a0a1a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.355, 1.855] } + ] + }, + "Demon": { + "background": { "sprite": "demon_gauntlet.png", "scale": 1.275 }, + "gauntlet": { "position": [-1.0, 22.0], "scale": 1.1, "zOrder": 2 }, + "particles": [ + { "string": "66a-1a3a0.3a20a90a27a11a0a37a38a0a0a0a0a0a0a5a1a0a0a0.694118a0a0.45098a0a0.054902a0a1a0a2a1a0a0a0.509804a0a0.172549a0a0a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.0, 1.0] }, + { "string": "29a-1a3a0.3a8a90a27a11a0a37a38a0a0a0a0a0a0a50a1a0a0a0.0509804a0a0.0392157a0a0.0352941a0a1a0a50a1a0a0a0.0509804a0a0.0392157a0a0.0352941a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.0, 1.0] }, + { "string": "31a-1a1a0.3a23a90a90a29a0a11a0a0a0a0a0a0a0a33a1a89a149a0.454902a0a0.321569a0a0.152941a0a1a0a50a1a145a68a0.454902a0a0.321569a0a0.152941a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a1a2a1a0a0a0a192a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.0, 1.0] }, + { "string": "30a-1a2a0.3a13a90a8a21a0a8a0a0a45a0a0a0a0a40a1a89a149a0.396078a0a0.27451a0a0.14902a0a1a0a24a1a145a68a0.141176a0a0.0352941a0a0.0313726a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.0, 1.0] }, + { "string": "30a-1a1a0.3a13a90a8a21a0a0a0a0a45a0a0a0a0a21a1a89a149a0.894118a0a0.631373a0a0.345098a0a1a0a6a1a145a68a0.894118a0a0.631373a0a0.345098a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a183a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.0, 1.0] } + ] + }, + "Castle": { + "background": { "sprite": "castle_gauntlet.png", "scale": 1.275 } + }, + "Galaxy": { + "background": { "sprite": "galaxy_gauntlet.png", "scale": 1.695 }, + "gauntlet": { "position": [0.0, 11.0], "scale": 0.975, "zOrder": 3 }, + "particles": [ + { "string": "11a-1a1a0.3a8a90a90a0a0a0a0a0a0a0a0a0a0a50a3a0a0a0.627451a0a0.286275a0a0.470588a0a1a0a50a3a106a70a0.627451a0a0.286275a0a0.470588a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a176a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 24.0], "scale": [1.61, 1.61] }, + { "string": "14a-1a1.2a0.3a9a112a6a42a0a15a0a0a0a0a0a0a0a4a0a340a0a0.913725a0a0.72549a0a0.337255a0a1a0a4a0a340a0a0.913725a0a0.72549a0a0.337255a0a1a0a0.3a0a0.3a0a0a0a0a0a0a0a0a2a1a0a0a0a31a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [-25.0, 111.0], "scale": [2.66, 3.71], "rotation": 180 }, + { "string": "38a-1a1.5a0.3a21a90a90a0a0a31a69a0a0a0a0a0a0a2a1a65a57a0.886275a0a0.866667a0a0.454902a0a1a0a5a1a0a0a0.886275a0a0.866667a0a0.454902a0a1a0a0.2a0a0.4a0a0a0a0a0a0a0a0a2a1a0a0a0a169a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [2.0, 6.0], "scale": [1.685, 1.485] }, + { "string": "11a-1a1.5a0.3a6a90a90a0a0a31a69a0a0a0a0a0a0a4a1a0a0a0.890196a0a0.376471a0a0.65098a0a1a0a7a1a52a55a0.890196a0a0.376471a0a0.65098a0a1a0a0.2a0a0.4a0a0a0a0a0a0a0a0a2a1a0a0a0a167a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [2.0, -2.0], "scale": [1.31, 1.635] }, + { "string": "4a-1a1a0.3a3a90a90a0a0a0a0a0a0a0a0a0a0a50a3a0a0a0.862745a0a0.352941a0a0.623529a0a1a0a50a3a106a22a0.862745a0a0.352941a0a0.623529a0a1a0a0.3a0a0.3a0a0a0a0a0a0a0a0a2a1a0a0a0a164a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 24.0], "scale": [1.785, 1.785] } + ] + }, + "Universe": { + "background": { "sprite": "universe_gauntlet.png", "scale": 1.27 }, + "gauntlet": { "position": [0.0, 16.0], "scale": 0.975, "zOrder": 3 }, + "particles": [ + { "string": "23a-1a3a0.3a6a90a180a29a0a11a0a0a0a0a0a0a0a38a1a0a0a0.0627451a0a0.0980392a0a0.105882a0a1a0a50a1a0a0a0.0627451a0a0.0980392a0a0.105882a0a1a0a0.1a0a0.5a0a10a0a28a0a0a0a1a2a1a0a1a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 11.0], "scale": [1.485, 2.685] }, + { "string": "20a-1a0.5a0a15a90a0a44a0a11a0a0a0a0a0a0a0a4a1a0a0a0.760784a0a0.447059a0a0.94902a0a1a0a4a1a0a0a0.760784a0a0.447059a0a0.94902a0a1a0a0.1a0a0.1a0a0a0a0a0a0a0a0a2a1a0a0a0a33a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [32.0, -74.0], "scale": [3.685, 8.31], "rotation": -20 }, + { "string": "19a-1a0.5a0a38a90a0a44a0a20a0a0a0a0a0a0a0a2a1a0a0a0.94902a0a0.67451a0a0.447059a0a1a0a2a1a0a0a0.94902a0a0.67451a0a0.447059a0a1a0a0.1a0a0.1a0a0a0a0a0a0a0a0a2a1a0a0a0a33a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [34.0, -96.0], "scale": [2.135, 8.935], "rotation": -20 }, + { "string": "20a-1a1a0a15a90a0a36a0a11a0a0a0a0a0a0a0a4a1a0a0a0.447059a0a0.654902a0a0.94902a0a1a0a4a1a0a0a0.447059a0a0.654902a0a0.94902a0a1a0a0.2a0a0.2a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [41.0, -92.0], "scale": [3.235, 6.585], "rotation": -20 }, + { "string": "11a-1a1a0.3a8a90a90a0a0a0a0a0a0a0a0a0a0a50a3a0a0a0.239216a0a0.403922a0a0.419608a0a1a0a50a3a106a70a0.239216a0a0.403922a0a0.419608a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a176a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 24.0], "scale": [1.71, 1.71] }, + { "string": "4a-1a1a0.3a3a90a90a0a0a0a0a0a0a0a0a0a0a50a3a0a0a0.32549a0a0.537255a0a0.560784a0a1a0a50a3a106a22a0.32549a0a0.537255a0a0.560784a0a1a0a0.3a0a0.3a0a0a0a0a0a0a0a0a2a1a0a0a0a190a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [-2.0, 24.0], "scale": [2.71, 2.71] } + ] + }, + "Cursed": { + "background": { "sprite": "cursed_gauntlet.png", "scale": 1.27 }, + "gauntlet": { "position": [1.0, 16.0], "scale": 1.0, "zOrder": 3 }, + "particles": [ + { "string": "5a-1a1a0.3a3a90a90a29a0a11a0a0a0a0a0a0a0a50a1a24a45a0.105882a0a0.380392a0a0.105882a0a1a0a44a1a48a28a0.105882a0a0.380392a0a0.105882a0a1a0a0a0a0a0a0a0a0a0a0a0a1a2a1a0a0a0a175a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [2.035, 2.035] }, + { "string": "5a-1a1a0.3a3a90a90a29a0a11a0a0a0a0a0a0a0a50a1a24a45a0.105882a0a0.380392a0a0.105882a0a1a0a44a1a48a28a0.105882a0a0.380392a0a0.105882a0a1a0a0a0a0a0a0a0a0a0a0a0a1a2a1a0a0a0a175a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [2.035, 2.035] }, + { "string": "93a-1a1a0.3a71a90a0a52a0a10a0a23a0a0a0a0a0a2a1a0a0a0.00392157a0a0.905882a0a0a0a1a0a2a1a30a0a0.00392157a0a0.905882a0a0a0a1a0a0.3a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a32a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [17.0, 94.0], "scale": [4.51, 3.335], "rotation": 180 } + ] + }, + "Doom": { + "background": { "sprite": "doom_gauntlet.png", "scale": 1.27 }, + "gauntlet": { "position": [0.0, 19.0], "scale": 1.025, "zOrder": 3 }, + "particles": [ + { "string": "66a-1a3a0.3a20a90a27a11a0a43a83a0a0a0a0a0a0a5a1a0a0a0.733333a0a0.607843a0a0.12549a0a1a0a3a1a0a0a0.733333a0a0.470588a0a0.12549a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, -7.0], "scale": [1.235, 1.235] }, + { "string": "44a-1a3a0.3a13a90a27a11a0a32a62a0a0a0a0a0a0a50a1a0a0a0.0666667a0a0.0509804a0a0.0470588a0a1a0a50a1a0a0a0.0666667a0a0.0509804a0a0.0470588a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, -13.0], "scale": [1.31, 1.435] }, + { "string": "6a-1a1.9a0a3a90a17a69a0a3a0a0a-102a0a0a0a0a4a1a57a105a1a0a1a0a1a0a1a0a4a1a0a0a1a0a1a0a1a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a145a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [2.035, 2.035] } + ] + }, + "Split": { + "background": { "sprite": "split_gauntlet.png", "scale": 1.27 }, + "gauntlet": { "position": [-1.0, 20.0], "scale": 0.975, "zOrder": 2 }, + "particles": [ + { "string": "48a-1a2a0.3a20a90a2a19a0a10a20a0a0a0a0a0a0a4a1a0a0a0.666667a0a0.360784a0a0.603922a0a1a0a2a1a0a0a0.666667a0a0.360784a0a0.603922a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a31a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [-28.0, -65.0], "scale": [2.18, 4.003] }, + { "string": "48a-1a2a0.3a20a90a2a19a0a10a20a0a0a0a0a0a0a4a1a0a0a0.454902a0a0.215686a0a0.403922a0a1a0a2a1a0a0a0.454902a0a0.215686a0a0.403922a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [-28.0, -65.0], "scale": [2.18, 4.003] }, + { "string": "48a-1a2a0.3a20a90a2a19a0a10a20a0a0a0a0a0a0a4a1a0a0a0.243137a0a0.329412a0a0.341176a0a1a0a2a1a0a0a0.243137a0a0.329412a0a0.341176a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a31a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [25.0, 65.0], "scale": [2.18, 4.003] }, + { "string": "48a-1a2a0.3a20a90a2a19a0a10a20a0a0a0a0a0a0a4a1a0a0a0.145098a0a0.203922a0a0.207843a0a1a0a2a1a0a0a0.145098a0a0.203922a0a0.207843a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [25.0, 65.0], "scale": [2.18, 4.003] }, + { "string": "30a-1a2a0.3a13a90a90a29a0a11a0a0a0a0a0a0a0a6a1a0a0a0.705882a0a0.34902a0a0.698039a0a1a0a2a1a0a0a0.584314a0a0.34902a0a0.705882a0a1a0a0a0a0.5a0a6a0a34a0a0a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 29.0], "scale": [1.955, 1.955], "rotation": 90 }, + { "string": "30a-1a2a0.3a13a90a90a29a0a11a0a0a0a0a0a0a0a6a1a0a0a0.254902a0a0.333333a0a0.388235a0a1a0a2a1a0a0a0.254902a0a0.333333a0a0.388235a0a1a0a0a0a0.5a0a6a0a34a0a0a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 29.0], "scale": [1.955, 1.955], "rotation": -90 }, + { "string": "30a-1a2a0.3a13a90a90a29a0a11a0a0a0a0a0a0a0a6a1a0a0a0.705882a0a0.34902a0a0.698039a0a1a0a2a1a0a0a0.584314a0a0.34902a0a0.705882a0a1a0a0a0a0.5a0a6a0a34a0a0a0a1a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 29.0], "scale": [1.955, 1.955], "rotation": 90 }, + { "string": "30a-1a2a0.3a13a90a90a29a0a11a0a0a0a0a0a0a0a6a1a0a0a0.254902a0a0.333333a0a0.388235a0a1a0a2a1a0a0a0.254902a0a0.333333a0a0.388235a0a1a0a0a0a0.5a0a6a0a34a0a0a0a1a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 29.0], "scale": [1.955, 1.955], "rotation": -90 } + ] + }, + "Monster": { + "background": { "sprite": "monster_gauntlet.png", "scale": 1.27 }, + "gauntlet": { "position": [0.0, 22.0], "scale": 1.075, "zOrder": 2 }, + "particles": [ + { "string": "30a-1a3a0.3a9a90a9a11a0a17a40a0a0a0a0a0a0a4a1a0a0a0.0509804a0a0.929412a0a0a0a1a0a2a1a0a0a0.360784a0a0.486275a0a0.352941a0a1a0a0.1a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a165a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, -37.0], "scale": [2.51, 1.985] }, + { "string": "66a-1a3a0.3a20a90a27a11a0a37a38a0a0a0a0a0a0a5a1a0a0a0.0156863a0a0.866667a0a0.027451a0a1a0a3a1a0a0a0.164706a0a0.509804a0a0a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, -38.0], "scale": [1.072, 2.475] }, + { "string": "18a-1a3a0.3a5a90a9a11a0a32a28a0a0a0a0a0a0a50a1a0a0a0.0352941a0a0.0901961a0a0.0313726a0a1a0a50a1a0a0a0.0352941a0a0.0901961a0a0.0313726a0a1a0a1a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, -48.0], "scale": [1.47, 1.957] } + ] + }, + "Mystery": { + "background": { "sprite": "mystery_gauntlet.png", "scale": 1.27 }, + "gauntlet": { "position": [3.0, 13.0], "scale": 0.975, "zOrder": 3 }, + "particles": [ + { "string": "30a-1a3a0.3a9a90a180a29a0a11a0a0a0a0a0a0a0a2a1a0a0a1a0a0.8a0a0.258824a0a1a0a8a1a0a0a1a0a0.8a0a0.258824a0a1a0a0.5a0a0.5a0a6a0a30a0a0a0a1a2a0a0a0a0a11a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [2.035, 2.035], "zOrder": 2 }, + { "string": "31a-1a3a0.3a9a90a180a0a0a29a82a0a0a0a0a0a0a4a1a0a0a0.388235a0a0.741176a0a1a0a1a0a15a1a0a0a0.388235a0a0.741176a0a1a0a1a0a1a0a1a0a6a0a30a0a0a0a0a2a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 0.0], "scale": [1.435, 1.435] } + ] + }, + "Strange": { + "background": { "sprite": "strange_gauntlet.png", "scale": 1.27 }, + "reverseGauntlet": true, + "gauntlet": { "position": [2.0, -18.0], "scale": 0.975, "zOrder": 2, "rotation": 180, "flipX": true }, + "particles": [ + { "string": "36a-1a3a0.3a6a-90a24a9a0a11a0a0a-7a0a0a0a0a2a1a76a325a0.592157a0a0.294118a0a0.658824a0a1a0a2a1a201a149a0.592157a0a0.294118a0a0.658824a0a1a0a0.3a0a0.3a0a0a0a0a0a0a0a0a2a0a0a0a0a96a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [2.0, -65.0], "scale": [2.48, 2.728], "rotation": 180, "zOrder": 2 }, + { "string": "17a-1a4a0.3a3a180a0a8a0a47a34a0a0a0a0a0a0a50a1a0a0a0.243137a0a0.239216a0a0.239216a0a1a0a50a1a0a0a0.454902a0a0.447059a0a0.447059a0a1a0a1a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [17.0, 60.0], "scale": [0.805, 1.155], "zOrder": 3 } + ] + }, + "Water": { + "background": { "sprite": "water_gauntlet.png", "scale": 1.27 } + }, + "Fire": { + "background": { "sprite": "fire_gauntlet.png", "scale": 1.27 }, + "gauntlet": { "position": [0.0, 15.0], "scale": 1.05, "zOrder": 2 }, + "particles": [ + { "string": "30a-1a2a0.3a13a90a8a21a0a8a0a0a45a0a0a0a0a50a1a89a149a0.396078a0a0.27451a0a0.14902a0a1a0a31a1a145a68a0.141176a0a0.0352941a0a0.0313726a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [-1.0, 0.0], "scale": [1.435, 0.935] }, + { "string": "30a-1a1a0.3a13a90a8a21a0a0a0a0a45a0a0a0a0a21a1a89a149a0.894118a0a0.631373a0a0.345098a0a1a0a13a1a145a68a0.894118a0a0.631373a0a0.345098a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a183a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [2.322, 1.347] }, + { "string": "19a-1a2a0.3a8a90a0a29a0a5a0a0a0a0a0a0a0a50a1a50a33a0.12549a0a0.0862745a0a0a0a1a0a30a1a50a30a0.12549a0a0.0862745a0a0a0a1a0a0.1a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a181a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.145, 1.795] }, + { "string": "31a-1a3a0.3a9a90a27a11a0a37a38a0a0a0a0a0a0a50a1a0a0a0.133333a0a0.0862745a0a0.0588235a0a1a0a50a1a0a0a0.0666667a0a0.0470588a0a0.0352941a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [1.0, -23.0], "scale": [1.27, 1.832] }, + { "string": "40a-1a3a0.3a12a90a13a11a0a48a78a0a0a0a0a0a0a5a3a0a0a0.439216a0a0.309804a0a0.129412a0a1a0a3a3a0a0a0.439216a0a0.309804a0a0.129412a0a1a0a0.1a0a0.3a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [2.0, -20.0], "scale": [1.205, 1.28] } + ] + }, + "Ice": { + "background": { "sprite": "ice_gauntlet.png", "scale": 1.27 }, + "gauntlet": { "position": [0.0, 15.0], "scale": 1.05, "zOrder": 2 }, + "particles": [ + { "string": "25a-1a1a0.3a19a90a90a0a0a0a0a0a0a0a0a0a0a12a1a0a98a0.0980392a0a0.176471a0a0.219608a0a1a0a36a1a0a0a0.0980392a0a0.176471a0a0.219608a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a191a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 17.0], "scale": [3.76, 3.76] }, + { "string": "200a-1a4a0.3a46a90a0a18a0a24a0a0a0a0a0a0a0a1a1a0a39a0.980392a0a1a0a0.980392a0a1a0a1a1a98a41a0.980392a0a1a0a0.980392a0a1a0a0.3a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a14a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [11.0, 112.0], "scale": [2.322, 3.097], "rotation": -174 }, + { "string": "44a-1a3a0.3a13a90a27a11a0a40a62a0a0a0a0a0a0a50a1a0a0a0.0431373a0a0.0627451a0a0.0666667a0a1a0a50a1a0a0a0.0431373a0a0.0627451a0a0.0666667a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, -11.0], "scale": [1.145, 1.795] }, + { "string": "38a-1a1.5a0.3a21a90a90a0a0a31a69a0a0a0a0a0a0a2a1a65a57a1a0a1a0a1a0a1a0a5a1a0a0a1a0a1a0a1a0a1a0a0.2a0a0.4a0a0a0a0a0a0a0a0a2a1a0a0a0a169a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.47, 1.957] } + ] + }, + "Poison": { + "background": { "sprite": "poison_gauntlet.png", "scale": 1.27 }, + "particles": [ + { "string": "31a-1a3a0.3a9a90a27a11a0a37a64a0a0a0a0a0a0a50a1a0a0a0.054902a0a0.129412a0a0.0627451a0a1a0a50a1a0a0a0.054902a0a0.129412a0a0.0627451a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 11.0], "scale": [1.26, 1.485] }, + { "string": "20a-1a3a0.3a6a90a22a11a0a33a55a0a0a0a0a0a0a1a1a0a0a0.137255a0a0.301961a0a0.133333a0a1a0a10a1a0a0a0.137255a0a0.301961a0a0.133333a0a1a0a0.1a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a40a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [-3.0, -13.0], "scale": [1.722, 1.397] }, + { "string": "4a-1a2.5a0.3a1a-90a0a0a10a35a0a0a-70a0a0a0a0a6a2a140a0a0.345098a0a0.690196a0a0.301961a0a1a0a4a2a140a0a0.345098a0a0.690196a0a0.301961a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a77a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 109.0], "scale": [1.145, 1.795] }, + { "string": "40a-1a3a0.3a12a90a13a11a0a48a78a0a0a0a0a0a0a3a1a0a0a0.129412a0a0.439216a0a0.168627a0a1a0a1a1a0a0a0.129412a0a0.439216a0a0.168627a0a1a0a0.1a0a0.3a0a0a0a0a0a0a0a0a2a1a0a0a0a192a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.27, 1.632] } + ] + }, + "Shadow": { + "background": { "sprite": "shadow_gauntlet.png", "scale": 1.745 }, + "gauntlet": { "position": [2.0, 26.0], "scale": 0.975, "zOrder": 2 }, + "particles": [ + { "string": "48a-1a3a0.3a14a90a27a6a0a40a57a0a0a0a0a0a0a50a1a0a0a0.0509804a0a0.0235294a0a0.0666667a0a1a0a50a1a0a0a0.0509804a0a0.0235294a0a0.0666667a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, -15.0], "scale": [1.31, 1.735] }, + { "string": "62a-1a1a0.3a47a90a90a29a0a11a0a0a0a0a0a0a0a50a1a0a59a0.0784314a0a0.0235294a0a0.0941176a0a1a0a38a1a103a65a0.0784314a0a0.0235294a0a0.0941176a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a1a2a1a0a0a0a190a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 25.0], "scale": [2.472, 2.472] }, + { "string": "62a-1a1a0.3a47a90a180a29a0a11a0a0a0a0a0a0a0a50a1a0a0a0.0313726a0a0.00392157a0a0.0470588a0a1a0a38a1a0a0a0.0313726a0a0.00392157a0a0.0470588a0a1a0a0.5a0a0.5a0a38a0a9a0a-85a26a1a2a1a0a0a0a183a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 25.0], "scale": [1.47, 1.47] }, + { "string": "62a-1a1a0.3a47a90a180a29a0a11a0a0a0a0a0a0a0a50a1a0a0a0.0313726a0a0.00392157a0a0.0431373a0a1a0a38a1a0a0a0.0313726a0a0.00392157a0a0.0431373a0a1a0a0.5a0a0.5a0a38a0a9a0a-85a26a1a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 25.0], "scale": [1.195, 1.195] }, + { "string": "40a-1a3a0.3a12a90a13a11a0a48a78a0a0a0a0a0a0a5a3a0a0a0.129412a0a0.439216a0a0.133333a0a1a0a3a3a0a0a0.129412a0a0.439216a0a0.133333a0a1a0a0.1a0a0.3a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, -16.0], "scale": [1.255, 1.43] } + ] + }, + "Lava": { + "background": { "sprite": "lava_gauntlet.png", "scale": 1.27 }, + "gauntlet": { "position": [0.0, 16.0], "scale": 0.95, "zOrder": 2 }, + "particles": [ + { "string": "40a-1a3a0.3a12a90a13a11a0a48a78a0a0a0a0a0a0a5a3a0a0a0.439216a0a0.309804a0a0.129412a0a1a0a3a3a0a0a0.439216a0a0.309804a0a0.129412a0a1a0a0.1a0a0.3a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, -16.0], "scale": [1.36, 1.36] }, + { "string": "59a-1a1a0.3a45a90a14a100a54a2a6a0a-135a0a46a0a0a20a8a0a0a1a0a0.756863a0a0.258824a0a1a0a1a1a0a0a1a0a0.694118a0a0.321569a0a1a0a0a0a0.1a0a0a0a0a0a0a0a0a2a1a0a0a1a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.522, 1.547] }, + { "string": "56a-1a1a0.3a43a90a16a103a81a2a6a0a-180a0a46a0a0a13a8a0a0a1a0a0.756863a0a0.258824a0a1a0a1a1a0a0a1a0a0.694118a0a0.321569a0a1a0a0a0a0.1a0a0a0a0a0a0a0a0a2a1a0a0a1a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.47, 1.37] }, + { "string": "56a-1a1a0.5a19a90a28a49a43a2a6a0a23a0a43a0a0a50a33a0a0a0.172549a0a0.160784a0a0.14902a0a0.47a0a50a38a0a0a0.247059a0a0.243137a0a0.239216a0a0.47a0a0a0a0.13a0a0a0a0a0a0a0a0a2a0a0a0a1a29a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.095, 0.845] }, + { "string": "59a-1a1a0.3a45a90a18a113a30a2a6a0a-192a0a46a0a0a20a8a0a0a1a0a0.505882a0a0.258824a0a1a0a1a1a0a0a1a0a0.505882a0a0.258824a0a1a0a0a0a0.1a0a0a0a0a0a0a0a0a2a1a0a0a1a158a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [1.255, 1.43] }, + { "string": "48a-1a3a0.3a14a90a27a6a0a40a57a0a0a0a0a0a0a50a1a0a0a0.0666667a0a0.0352941a0a0.0196078a0a1a0a50a1a0a0a0.0666667a0a0.0352941a0a0.0196078a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, -18.0], "scale": [1.235, 1.835] } + ] + }, + "Time": { "background": { "sprite": "time_gauntlet.png", "scale": 1.22 } }, + "Spike": { "background": { "sprite": "spike_gauntlet.png", "scale": 1.92 } }, + "Cyborg": { "background": { "sprite": "cyborg_gauntlet.png", "scale": 1.27 } }, + "Inferno": { "background": { "sprite": "inferno_gauntlet.png", "scale": 1.27 } }, + "Death": { "background": { "sprite": "death_gauntlet.png", "scale": 1.27 } }, + "Magic": { "background": { "sprite": "magic_gauntlet.png", "scale": 1.27 } }, + "Chaos": { "background": { "sprite": "chaos_gauntlet.png", "scale": 1.27 } }, + "Force": { "background": { "sprite": "force_gauntlet.png", "scale": 1.27 } }, + "NCS I": { + "background": { "sprite": "ncs_gauntlet_1.png", "scale": 1.27 }, + "gauntlet": { "position": [0.0, 16.0], "scale": 0.9, "zOrder": 3 }, + "particles": [ + { "string": "25a-1a1a0.3a19a90a90a0a0a0a0a0a0a0a0a0a0a23a1a0a98a0.0980392a0a0.176471a0a0.219608a0a1a0a50a1a0a0a0.0980392a0a0.176471a0a0.219608a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a185a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 20.0], "scale": [2.06, 2.06], "zOrder": 2 }, + { "string": "25a-1a1a0.3a19a90a90a0a0a0a0a0a0a0a0a0a0a12a1a0a98a0.0980392a0a0.176471a0a0.219608a0a1a0a36a1a0a0a0.0980392a0a0.176471a0a0.219608a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a167a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [4.21, 4.21], "zOrder": 2 }, + { "string": "30a-1a2.5a0.3a10a90a12a19a0a23a0a0a11a0a0a0a0a4a1a0a0a0.313726a0a0.458824a0a0.529412a0a1a0a2a1a0a0a0.313726a0a0.458824a0a0.529412a0a1a0a0a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a19a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, -81.0], "scale": [2.035, 2.035], "zOrder": 0 } + ] + }, + "NCS II": { + "background": { "sprite": "ncs_gauntlet_2.png", "scale": 1.27 }, + "gauntlet": { "position": [0.0, 16.0], "scale": 0.9, "zOrder": 3 }, + "particles": [ + { "string": "25a-1a1a0.3a19a90a90a0a0a0a0a0a0a0a0a0a0a23a1a0a98a0.301961a0a0.156863a0a0.341176a0a1a0a50a1a0a0a0.301961a0a0.156863a0a0.341176a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a185a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, 20.0], "scale": [2.06, 2.06], "zOrder": 2 }, + { "string": "25a-1a1a0.3a19a90a90a0a0a0a0a0a0a0a0a0a0a12a1a0a98a0.301961a0a0.156863a0a0.341176a0a1a0a36a1a0a0a0.301961a0a0.156863a0a0.341176a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a167a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": null, "scale": [4.21, 4.21], "zOrder": 2 }, + { "string": "30a-1a2.5a0.3a10a90a12a19a0a23a0a0a11a0a0a0a0a4a1a0a0a0.482353a0a0.317647a0a0.533333a0a1a0a2a1a0a0a0.482353a0a0.317647a0a0.533333a0a1a0a0a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a19a0a0a0a0a0a0a0a0a0a0a0a0a0a0", "position": [0.0, -81.0], "scale": [2.035, 2.035], "zOrder": 0 } + ] + }, + "Discord": { + "background": { "sprite": "discord_gauntlet.png", "scale": 1.245, "offsetY": 3 }, + "itemZOrder": 1 + }, + "Space": { + "background": { "sprite": "space_gauntlet.png", "scale": 1.245, "offsetY": 3 }, + "itemZOrder": 1 + }, + "Cosmos": { + "background": { "sprite": "cosmos_gauntlet.png", "scale": 1.245, "offsetY": 3 }, + "itemZOrder": 1 + } +} diff --git a/src/MoreLeaderboards/CustomScoreCell.cpp b/src/MoreLeaderboards/CustomScoreCell.cpp deleted file mode 100644 index 267f06d..0000000 --- a/src/MoreLeaderboards/CustomScoreCell.cpp +++ /dev/null @@ -1,436 +0,0 @@ -#include -#include -#include "MoreLeaderboards.h" -#include "SelectRegion.h" -#include "LevelHelper.cpp" - -#include -using namespace geode::prelude; - - -class $modify(CustomScoreCell, GJScoreCell) { - void loadFromScore(GJUserScore* score) { - GJScoreCell::loadFromScore(score); - - CCLayer* layer = as(this->getChildren()->objectAtIndex(1)); - if (layer) { - // Search for flag - std::string data_flag = MoreLeaderboards::data_response_moreLB; - - if (data_flag == "") return; - - auto position = layer->getPosition(); - - RowLayout* layout = RowLayout::create(); - layout->setGap(3); - layout->setAxisAlignment(AxisAlignment::Start); - layout->setCrossAxisOverflow(true); - - CCMenu* menu = CCMenu::create(); - menu->setContentSize(CCSize(283, 21.580f)); - menu->setPosition(206, 42); - - // Move child to menu with layout - auto starsLabel = as(layer->getChildByIDRecursive("stars-label")); - starsLabel->setLayoutOptions( - AxisLayoutOptions::create()->setAutoScale(true)->setScaleLimits(0, 0.5F)->setScalePriority(1) - ); - auto starsIcon = as(layer->getChildByIDRecursive("stars-icon")); - starsIcon->setLayoutOptions( - AxisLayoutOptions::create()->setAutoScale(true)->setScaleLimits(0, 0.5F)->setScalePriority(1) - ); - auto moonsLabel = as(layer->getChildByIDRecursive("moons-label")); - moonsLabel->setLayoutOptions( - AxisLayoutOptions::create()->setAutoScale(true)->setScaleLimits(0, 0.5F)->setScalePriority(1) - ); - auto moonsIcon = as(layer->getChildByIDRecursive("moons-icon")); - moonsIcon->setLayoutOptions( - AxisLayoutOptions::create()->setAutoScale(true)->setScaleLimits(0, 0.5F)->setScalePriority(1) - ); - - // Username control - std::string playerName = as(as(layer->getChildByIDRecursive("player-name"))->getChildren()->objectAtIndex(0))->getString(); - CCMenu* menu_playername = CCMenu::create(); - menu_playername->setContentSize(as(layer->getChildByIDRecursive("player-name"))->getContentSize()); - menu_playername->setLayout( - RowLayout::create()->setGap(3)->setAxisAlignment(AxisAlignment::Start) - ); - auto playerNameBM = CCLabelBMFont::create(playerName.c_str(), "goldFont.fnt"); - auto playerNameBtn = CCMenuItemSpriteExtra::create( - playerNameBM, - this, - (SEL_MenuHandler)&CustomScoreCell::onViewProfile - ); - playerNameBtn->setLayoutOptions( - AxisLayoutOptions::create()->setAutoScale(true)->setScaleLimits(0.5F, 0.8F)->setScalePriority(1) - ); - - std::vector dataString = MoreLeaderboards::getWords(data_flag, "#"); - std::vector users = MoreLeaderboards::getWords(dataString[0], "|"); - - std::string count_diff = "0"; - - while (users.size() > 0) { - std::string user = users[0]; - - std::vector data_info = MoreLeaderboards::getWords(user, ":"); - while (data_info.size() > 0) { - std::string id = data_info[0]; - std::string info = data_info[1]; - - if (id == "1") { - if (info != playerName) break; - } - if (id == "9989") { - count_diff = info; - } - if (id == "9990") { - if (info == "XX") break; - auto flagSpr = CCSprite::createWithSpriteFrameName((""_spr+info+".png").c_str()); - flagSpr->setPosition({ 20, 15 }); - flagSpr->setScaleY(20 / flagSpr->getContentHeight() * 0.50); - flagSpr->setScaleX(std::min(1.0f, 30 / flagSpr->getContentWidth())); - flagSpr->setLayoutOptions( - AxisLayoutOptions::create()->setAutoScale(true)->setScalePriority(1) - ); - menu_playername->addChild(flagSpr); - } - - data_info.erase(data_info.begin()); - data_info.erase(data_info.begin()); - } - - users.erase(users.begin()); - }; - - menu_playername->addChild(playerNameBtn); - menu_playername->updateLayout(); - - OPT(layer->getChildByID("stars-label"))->removeFromParentAndCleanup(true); - OPT(layer->getChildByID("stars-icon"))->removeFromParentAndCleanup(true); - OPT(layer->getChildByID("moons-label"))->removeFromParentAndCleanup(true); - OPT(layer->getChildByID("moons-icon"))->removeFromParentAndCleanup(true); - OPT(layer->getChildByID("main-menu"))->removeFromParentAndCleanup(true); - - menu->addChild(menu_playername); - menu->addChild(starsLabel); - menu->addChild(starsIcon); - menu->addChild(moonsLabel); - menu->addChild(moonsIcon); - - menu->setLayout(layout); - menu->updateLayout(); - - // get main layer - CCLayer* mainLayer = nullptr; - CCObject* obj; - CCARRAY_FOREACH(this->getChildren(), obj) { - CCLayer* search = typeinfo_cast(obj); - if (search != nullptr && search->getChildrenCount() > 2) { - mainLayer = search; - break; - } - } - auto statsMenu = mainLayer->getChildByIDRecursive("stats-menu"); - - // BetterProgression part - Loader* loader = Loader::get(); - if (!loader->isModLoaded("itzkiba.better_progression") && MoreLeaderboards::g_tab == StatsListType::BetterProgression) { - int currentEXP = LevelHelper::calculateTotalEXP(score); - int currentLevel = LevelHelper::getLevelFromEXP(currentEXP); - - auto badgeSpr = SpriteHelper::createFullSprite(currentLevel); - badgeSpr->setPosition({75, 17.5}); - badgeSpr->setScale(0.62); - - mainLayer->addChild(badgeSpr); - - statsMenu->setScale(0.83); - statsMenu->setPositionX(statsMenu->getPositionX() + 13.f); - } - - // Classic & Platformer Demons part - auto classic_sprite = CCSprite::createWithSpriteFrameName("star_small01_001.png"); - classic_sprite->setPositionX(30); - classic_sprite->setScale(1.2f); - - auto platformer_sprite = CCSprite::createWithSpriteFrameName("moon_small01_001.png"); - platformer_sprite->setPositionX(30); - platformer_sprite->setScale(1.2f); - - auto pointercrate = CCSprite::createWithSpriteFrameName("diffIcon_06_btn_001.png"); - auto pointercrate_text = CCLabelBMFont::create("PC", "goldFont.fnt"); - pointercrate_text->setPosition(28, 0); - pointercrate_text->setScale(0.5f); - pointercrate->addChild(pointercrate_text); - - auto easydemon_sprite_classic = CCSprite::createWithSpriteFrameName("diffIcon_07_btn_001.png"); - easydemon_sprite_classic->addChild(classic_sprite); - auto mediumdemon_sprite_classic = CCSprite::createWithSpriteFrameName("diffIcon_08_btn_001.png"); - mediumdemon_sprite_classic->addChild(classic_sprite); - auto harddemon_sprite_classic = CCSprite::createWithSpriteFrameName("diffIcon_06_btn_001.png"); - harddemon_sprite_classic->addChild(classic_sprite); - auto insane_sprite_classic = CCSprite::createWithSpriteFrameName("diffIcon_09_btn_001.png"); - insane_sprite_classic->addChild(classic_sprite); - auto extreme_sprite_classic = CCSprite::createWithSpriteFrameName("diffIcon_10_btn_001.png"); - extreme_sprite_classic->addChild(classic_sprite); - - auto easydemon_sprite_platformer = CCSprite::createWithSpriteFrameName("diffIcon_07_btn_001.png"); - easydemon_sprite_platformer->addChild(platformer_sprite); - auto mediumdemon_sprite_platformer = CCSprite::createWithSpriteFrameName("diffIcon_08_btn_001.png"); - mediumdemon_sprite_platformer->addChild(platformer_sprite); - auto harddemon_sprite_platformer = CCSprite::createWithSpriteFrameName("diffIcon_06_btn_001.png"); - harddemon_sprite_platformer->addChild(platformer_sprite); - auto insane_sprite_platformer = CCSprite::createWithSpriteFrameName("diffIcon_09_btn_001.png"); - insane_sprite_platformer->addChild(platformer_sprite); - auto extreme_sprite_platformer = CCSprite::createWithSpriteFrameName("diffIcon_10_btn_001.png"); - extreme_sprite_platformer->addChild(platformer_sprite); - - // Change Z orders - statsMenu->getChildByIDRecursive("diamonds-label")->setZOrder(0); - statsMenu->getChildByIDRecursive("diamonds-icon")->setZOrder(1); - statsMenu->getChildByIDRecursive("coins-label")->setZOrder(2); - statsMenu->getChildByIDRecursive("coins-icon")->setZOrder(3); - statsMenu->getChildByIDRecursive("user-coins-label")->setZOrder(4); - statsMenu->getChildByIDRecursive("user-coins-icon")->setZOrder(5); - statsMenu->getChildByIDRecursive("demons-label")->setZOrder(6); - statsMenu->getChildByIDRecursive("demons-icon")->setZOrder(7); - auto cp_label = statsMenu->getChildByIDRecursive("creator-points-label"); - if (cp_label) cp_label->setZOrder(8); - auto cp_icon = statsMenu->getChildByIDRecursive("creator-points-icon"); - if (cp_icon) cp_icon->setZOrder(9); - - auto demon_icon = mainLayer->getChildByIDRecursive("demons-icon"); - auto demon_icon_pos = demon_icon->getPosition(); - auto demon_icon_scale = demon_icon->getScale(); - auto demon_icon_z = demon_icon->getZOrder(); - auto demon_icon_tag = demon_icon->getTag(); - auto demon_icon_layout = demon_icon->getLayoutOptions(); - auto demon_label = mainLayer->getChildByIDRecursive("demons-label"); - auto demon_label_pos = demon_label->getPosition(); - auto demon_label_scale = demon_label->getScale(); - auto demon_label_z = demon_label->getZOrder(); - auto demon_label_tag = demon_label->getTag(); - auto demon_label_layout = demon_label->getLayoutOptions(); - - switch (MoreLeaderboards::g_tab) { - case StatsListType::platformerDemonsEasy: - demon_icon->removeFromParent(); - demon_icon = easydemon_sprite_platformer; - demon_icon->setPosition(demon_icon_pos); - demon_icon->setScale(demon_icon_scale); - demon_icon->setLayoutOptions(demon_icon_layout); - demon_icon->setTag(demon_icon_tag); - demon_icon->setZOrder(demon_icon_z); - statsMenu->addChild(easydemon_sprite_platformer); - - demon_label->removeFromParent(); - demon_label = CCLabelBMFont::create(count_diff.c_str(), "bigFont.fnt"); - demon_label->setPosition(demon_label_pos); - demon_label->setScale(demon_label_scale); - demon_label->setZOrder(demon_label_z); - demon_label->setTag(demon_label_tag); - demon_label->setLayoutOptions(demon_label_layout); - statsMenu->addChild(demon_label); - break; - case StatsListType::platformerDemonsMedium: - demon_icon->removeFromParent(); - demon_icon = mediumdemon_sprite_platformer; - demon_icon->setPosition(demon_icon_pos); - demon_icon->setScale(demon_icon_scale); - demon_icon->setLayoutOptions(demon_icon_layout); - demon_icon->setTag(demon_icon_tag); - demon_icon->setZOrder(demon_icon_z); - statsMenu->addChild(mediumdemon_sprite_platformer); - - demon_label->removeFromParent(); - demon_label = CCLabelBMFont::create(count_diff.c_str(), "bigFont.fnt"); - demon_label->setPosition(demon_label_pos); - demon_label->setScale(demon_label_scale); - demon_label->setZOrder(demon_label_z); - demon_label->setTag(demon_label_tag); - demon_label->setLayoutOptions(demon_label_layout); - statsMenu->addChild(demon_label); - break; - case StatsListType::platformerDemonsHard: - demon_icon->removeFromParent(); - demon_icon = harddemon_sprite_platformer; - demon_icon->setPosition(demon_icon_pos); - demon_icon->setScale(demon_icon_scale); - demon_icon->setLayoutOptions(demon_icon_layout); - demon_icon->setTag(demon_icon_tag); - demon_icon->setZOrder(demon_icon_z); - statsMenu->addChild(harddemon_sprite_platformer); - - demon_label->removeFromParent(); - demon_label = CCLabelBMFont::create(count_diff.c_str(), "bigFont.fnt"); - demon_label->setPosition(demon_label_pos); - demon_label->setScale(demon_label_scale); - demon_label->setZOrder(demon_label_z); - demon_label->setTag(demon_label_tag); - demon_label->setLayoutOptions(demon_label_layout); - statsMenu->addChild(demon_label); - break; - case StatsListType::platformerDemonsInsane: - demon_icon->removeFromParent(); - demon_icon = insane_sprite_platformer; - demon_icon->setPosition(demon_icon_pos); - demon_icon->setScale(demon_icon_scale); - demon_icon->setLayoutOptions(demon_icon_layout); - demon_icon->setTag(demon_icon_tag); - demon_icon->setZOrder(demon_icon_z); - statsMenu->addChild(insane_sprite_platformer); - - demon_label->removeFromParent(); - demon_label = CCLabelBMFont::create(count_diff.c_str(), "bigFont.fnt"); - demon_label->setPosition(demon_label_pos); - demon_label->setScale(demon_label_scale); - demon_label->setZOrder(demon_label_z); - demon_label->setTag(demon_label_tag); - demon_label->setLayoutOptions(demon_label_layout); - statsMenu->addChild(demon_label); - break; - case StatsListType::platformerDemonsExtreme: - demon_icon->removeFromParent(); - demon_icon = extreme_sprite_platformer; - demon_icon->setPosition(demon_icon_pos); - demon_icon->setScale(demon_icon_scale); - demon_icon->setLayoutOptions(demon_icon_layout); - demon_icon->setTag(demon_icon_tag); - demon_icon->setZOrder(demon_icon_z); - statsMenu->addChild(extreme_sprite_platformer); - - demon_label->removeFromParent(); - demon_label = CCLabelBMFont::create(count_diff.c_str(), "bigFont.fnt"); - demon_label->setPosition(demon_label_pos); - demon_label->setScale(demon_label_scale); - demon_label->setZOrder(demon_label_z); - demon_label->setTag(demon_label_tag); - demon_label->setLayoutOptions(demon_label_layout); - statsMenu->addChild(demon_label); - break; - case StatsListType::classicDemonsEasy: - demon_icon->removeFromParent(); - demon_icon = easydemon_sprite_classic; - demon_icon->setPosition(demon_icon_pos); - demon_icon->setScale(demon_icon_scale); - demon_icon->setLayoutOptions(demon_icon_layout); - demon_icon->setTag(demon_icon_tag); - demon_icon->setZOrder(demon_icon_z); - statsMenu->addChild(easydemon_sprite_classic); - - demon_label->removeFromParent(); - demon_label = CCLabelBMFont::create(count_diff.c_str(), "bigFont.fnt"); - demon_label->setPosition(demon_label_pos); - demon_label->setScale(demon_label_scale); - demon_label->setZOrder(demon_label_z); - demon_label->setTag(demon_label_tag); - demon_label->setLayoutOptions(demon_label_layout); - statsMenu->addChild(demon_label); - break; - case StatsListType::classicDemonsMedium: - demon_icon->removeFromParent(); - demon_icon = mediumdemon_sprite_classic; - demon_icon->setPosition(demon_icon_pos); - demon_icon->setScale(demon_icon_scale); - demon_icon->setLayoutOptions(demon_icon_layout); - demon_icon->setTag(demon_icon_tag); - demon_icon->setZOrder(demon_icon_z); - statsMenu->addChild(mediumdemon_sprite_classic); - - demon_label->removeFromParent(); - demon_label = CCLabelBMFont::create(count_diff.c_str(), "bigFont.fnt"); - demon_label->setPosition(demon_label_pos); - demon_label->setScale(demon_label_scale); - demon_label->setZOrder(demon_label_z); - demon_label->setTag(demon_label_tag); - demon_label->setLayoutOptions(demon_label_layout); - statsMenu->addChild(demon_label); - break; - case StatsListType::classicDemonsHard: - demon_icon->removeFromParent(); - demon_icon = harddemon_sprite_classic; - demon_icon->setPosition(demon_icon_pos); - demon_icon->setScale(demon_icon_scale); - demon_icon->setLayoutOptions(demon_icon_layout); - demon_icon->setTag(demon_icon_tag); - demon_icon->setZOrder(demon_icon_z); - statsMenu->addChild(harddemon_sprite_classic); - - demon_label->removeFromParent(); - demon_label = CCLabelBMFont::create(count_diff.c_str(), "bigFont.fnt"); - demon_label->setPosition(demon_label_pos); - demon_label->setScale(demon_label_scale); - demon_label->setZOrder(demon_label_z); - demon_label->setTag(demon_label_tag); - demon_label->setLayoutOptions(demon_label_layout); - statsMenu->addChild(demon_label); - break; - case StatsListType::classicDemonsInsane: - demon_icon->removeFromParent(); - demon_icon = insane_sprite_classic; - demon_icon->setPosition(demon_icon_pos); - demon_icon->setScale(demon_icon_scale); - demon_icon->setLayoutOptions(demon_icon_layout); - demon_icon->setTag(demon_icon_tag); - demon_icon->setZOrder(demon_icon_z); - statsMenu->addChild(insane_sprite_classic); - - demon_label->removeFromParent(); - demon_label = CCLabelBMFont::create(count_diff.c_str(), "bigFont.fnt"); - demon_label->setPosition(demon_label_pos); - demon_label->setScale(demon_label_scale); - demon_label->setZOrder(demon_label_z); - demon_label->setTag(demon_label_tag); - demon_label->setLayoutOptions(demon_label_layout); - statsMenu->addChild(demon_label); - break; - case StatsListType::classicDemonsExtreme: - demon_icon->removeFromParent(); - demon_icon = extreme_sprite_classic; - demon_icon->setPosition(demon_icon_pos); - demon_icon->setScale(demon_icon_scale); - demon_icon->setLayoutOptions(demon_icon_layout); - demon_icon->setTag(demon_icon_tag); - demon_icon->setZOrder(demon_icon_z); - statsMenu->addChild(extreme_sprite_classic); - - demon_label->removeFromParent(); - demon_label = CCLabelBMFont::create(count_diff.c_str(), "bigFont.fnt"); - demon_label->setPosition(demon_label_pos); - demon_label->setScale(demon_label_scale); - demon_label->setZOrder(demon_label_z); - demon_label->setTag(demon_label_tag); - demon_label->setLayoutOptions(demon_label_layout); - statsMenu->addChild(demon_label); - break; - case StatsListType::Pointercrate: - demon_icon->removeFromParent(); - demon_icon = pointercrate; - demon_icon->setPosition(demon_icon_pos); - demon_icon->setScale(demon_icon_scale); - demon_icon->setLayoutOptions(demon_icon_layout); - demon_icon->setTag(demon_icon_tag); - demon_icon->setZOrder(demon_icon_z); - statsMenu->addChild(pointercrate); - - demon_label->removeFromParent(); - demon_label = CCLabelBMFont::create(count_diff.c_str(), "bigFont.fnt"); - demon_label->setPosition(demon_label_pos); - demon_label->setScale(demon_label_scale); - demon_label->setZOrder(demon_label_z); - demon_label->setTag(demon_label_tag); - demon_label->setLayoutOptions(demon_label_layout); - statsMenu->addChild(demon_label); - break; - default: - break; - } - - statsMenu->updateLayout(); - - layer->addChild(menu); - layer->updateLayout(); - } - } -}; diff --git a/src/MoreLeaderboards/LevelHelper.cpp b/src/MoreLeaderboards/LevelHelper.cpp deleted file mode 100644 index 28f7454..0000000 --- a/src/MoreLeaderboards/LevelHelper.cpp +++ /dev/null @@ -1,414 +0,0 @@ -#include "../includes.h" - -#define STAR_EXP 5 -#define MOON_EXP 5 -#define DIAMOND_EXP 2 -#define GOLD_COIN_EXP 100 -#define USER_COIN_EXP 20 -#define DEMON_EXP 75 -#define CP_EXP 5000 - -class LevelHelper { - public: - inline static int calculateTotalEXP(GJUserScore* score) { - int totalEXP = 0; - totalEXP += (STAR_EXP * score->m_stars); - totalEXP += (MOON_EXP * score->m_moons); - totalEXP += (DIAMOND_EXP * score->m_diamonds); - totalEXP += (GOLD_COIN_EXP * score->m_secretCoins); - totalEXP += (USER_COIN_EXP * score->m_userCoins); - totalEXP += (DEMON_EXP * score->m_demons); - totalEXP += (CP_EXP * score->m_creatorPoints); - - return totalEXP; - } - - inline static int getEXPRequiredForLevel(int level) { - return (50 * (level * level) + (50 * level)); - } - - inline static int getLevelFromEXP(int exp) { - return (sqrt(2*exp + 25) - 5) / 10.0; - } -}; - -class SpriteHelper { - public: - inline static CCSprite* createFullSprite(int currentLevel) { - auto badgeSprite = SpriteHelper::getBadgeFromLevel(currentLevel); - badgeSprite->setID("itzkiba.better_progression/tier-badge"); - badgeSprite->setZOrder(10); - - auto badgeLabel = CCLabelBMFont::create(std::to_string(currentLevel).c_str(), "bigFont.fnt"); - badgeLabel->setZOrder(11); - badgeLabel->setScale((currentLevel >= 100 ? 0.3 : 0.4)); - badgeLabel->setPosition({badgeSprite->getContentSize().width / 2, badgeSprite->getContentSize().height / 2 + 1.f}); - badgeSprite->addChild(badgeLabel); - - auto badgeShadow = CCSprite::createWithSpriteFrameName("itzkiba.better_progression/shadow.png"); - badgeShadow->setZOrder(-5); - badgeShadow->setScale(0.9); - badgeShadow->setPosition({badgeSprite->getContentSize().width / 2, badgeSprite->getContentSize().height / 2}); - badgeShadow->setOpacity(100); - badgeSprite->addChild(badgeShadow); - - auto badgeGlow = SpriteHelper::getGlowFromLevel(currentLevel); - if (badgeGlow != nullptr && currentLevel <= 350) { - badgeGlow->setZOrder(-3); - badgeGlow->setPosition({badgeSprite->getContentSize().width / 2, badgeSprite->getContentSize().height / 2}); - badgeGlow->setScaleX(0.975); - badgeGlow->setScaleY(0.95); - badgeSprite->addChild(badgeGlow); - - ccBlendFunc blending = {GL_ONE, GL_ONE}; - badgeGlow->setBlendFunc(blending); - - if (currentLevel >= 200 && currentLevel <= 224) - badgeGlow->setColor({ 255, 156, 110 }); - if (currentLevel >= 225 && currentLevel <= 249) - badgeGlow->setColor({ 90, 255, 148 }); - if (currentLevel >= 250 && currentLevel <= 274) - badgeGlow->setColor({ 65, 239, 255 }); - if (currentLevel >= 275 && currentLevel <= 299) - badgeGlow->setColor({ 245, 108, 255 }); - - auto fadein = CCEaseSineInOut::create(CCFadeTo::create(0.9f, 50)); - auto fadeout = CCEaseSineInOut::create(CCFadeTo::create(0.9f, 255)); - auto sequence = CCSequence::create(fadein, fadeout, nullptr); - auto repeatSequence = CCRepeatForever::create(sequence); - - badgeGlow->runAction(repeatSequence); - } - - return badgeSprite; - } - - inline static CCSprite* getBadgeFromLevel(int level) { - if (level >= 0 && level <= 4) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier0_0.png"); - } - if (level >= 5 && level <= 9) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier0_1.png"); - } - if (level >= 10 && level <= 14) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier0_2.png"); - } - if (level >= 15 && level <= 19) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier0_3.png"); - } - if (level >= 20 && level <= 24) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier0_4.png"); - } - - if (level >= 25 && level <= 29) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier1_0.png"); - } - if (level >= 30 && level <= 34) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier1_1.png"); - } - if (level >= 35 && level <= 39) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier1_2.png"); - } - if (level >= 40 && level <= 44) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier1_3.png"); - } - if (level >= 45 && level <= 49) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier1_4.png"); - } - - if (level >= 50 && level <= 54) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier2_0.png"); - } - if (level >= 55 && level <= 59) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier2_1.png"); - } - if (level >= 60 && level <= 64) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier2_2.png"); - } - if (level >= 65 && level <= 69) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier2_3.png"); - } - if (level >= 70 && level <= 74) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier2_4.png"); - } - - if (level >= 75 && level <= 79) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier3_0.png"); - } - if (level >= 80 && level <= 84) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier3_1.png"); - } - if (level >= 85 && level <= 89) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier3_2.png"); - } - if (level >= 90 && level <= 94) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier3_3.png"); - } - if (level >= 95 && level <= 99) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier3_4.png"); - } - - if (level >= 100 && level <= 104) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier4_0.png"); - } - if (level >= 105 && level <= 109) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier4_1.png"); - } - if (level >= 110 && level <= 114) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier4_2.png"); - } - if (level >= 115 && level <= 119) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier4_3.png"); - } - if (level >= 120 && level <= 124) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier4_4.png"); - } - - if (level >= 125 && level <= 129) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier5_0.png"); - } - if (level >= 130 && level <= 134) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier5_1.png"); - } - if (level >= 135 && level <= 139) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier5_2.png"); - } - if (level >= 140 && level <= 144) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier5_3.png"); - } - if (level >= 145 && level <= 149) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier5_4.png"); - } - - if (level >= 150 && level <= 154) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier6_0.png"); - } - if (level >= 155 && level <= 159) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier6_1.png"); - } - if (level >= 160 && level <= 164) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier6_2.png"); - } - if (level >= 165 && level <= 169) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier6_3.png"); - } - if (level >= 170 && level <= 174) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier6_4.png"); - } - - if (level >= 175 && level <= 179) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier7_0.png"); - } - if (level >= 180 && level <= 184) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier7_1.png"); - } - if (level >= 185 && level <= 189) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier7_2.png"); - } - if (level >= 190 && level <= 194) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier7_3.png"); - } - if (level >= 195 && level <= 199) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier7_4.png"); - } - - if (level >= 200 && level <= 204) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier8_0.png"); - } - if (level >= 205 && level <= 209) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier8_1.png"); - } - if (level >= 210 && level <= 214) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier8_2.png"); - } - if (level >= 215 && level <= 219) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier8_3.png"); - } - if (level >= 220 && level <= 224) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier8_4.png"); - } - - if (level >= 225 && level <= 229) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier9_0.png"); - } - if (level >= 230 && level <= 234) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier9_1.png"); - } - if (level >= 235 && level <= 239) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier9_2.png"); - } - if (level >= 240 && level <= 244) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier9_3.png"); - } - if (level >= 245 && level <= 249) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier9_4.png"); - } - - if (level >= 250 && level <= 254) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier10_0.png"); - } - if (level >= 255 && level <= 259) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier10_1.png"); - } - if (level >= 260 && level <= 264) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier10_2.png"); - } - if (level >= 265 && level <= 269) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier10_3.png"); - } - if (level >= 270 && level <= 274) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier10_4.png"); - } - - if (level >= 275 && level <= 279) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier11_0.png"); - } - if (level >= 280 && level <= 284) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier11_1.png"); - } - if (level >= 285 && level <= 289) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier11_2.png"); - } - if (level >= 290 && level <= 294) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier11_3.png"); - } - if (level >= 295 && level <= 299) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier11_4.png"); - } - if (level >= 300 && level <= 349) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier12.png"); - } - // TEMP - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/tier0_0.png"); - } - - inline static CCSprite* getGlowFromLevel(int level) { - if (level >= 200 && level <= 204) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_0.png"); - } - if (level >= 205 && level <= 209) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_1.png"); - } - if (level >= 210 && level <= 214) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_2.png"); - } - if (level >= 215 && level <= 219) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_3.png"); - } - if (level >= 220 && level <= 224) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_4.png"); - } - - if (level >= 225 && level <= 229) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_0.png"); - } - if (level >= 230 && level <= 234) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_1.png"); - } - if (level >= 235 && level <= 239) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_2.png"); - } - if (level >= 240 && level <= 244) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_3.png"); - } - if (level >= 245 && level <= 249) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_4.png"); - } - - if (level >= 250 && level <= 254) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_0.png"); - } - if (level >= 255 && level <= 259) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_1.png"); - } - if (level >= 260 && level <= 264) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_2.png"); - } - if (level >= 265 && level <= 269) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_3.png"); - } - if (level >= 270 && level <= 274) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_4.png"); - } - - if (level >= 275 && level <= 279) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_0.png"); - } - if (level >= 280 && level <= 284) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_1.png"); - } - if (level >= 285 && level <= 289) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_2.png"); - } - if (level >= 290 && level <= 294) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_3.png"); - } - if (level >= 295 && level <= 299) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_4.png"); - } - if (level >= 300 && level <= 349) { - return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_4.png"); - } - - return nullptr; - } - - inline static CCSprite* getMostEXPIcon(GJUserScore* score) { - int starEXP = score->m_stars * STAR_EXP; - int moonEXP = score->m_moons * MOON_EXP; - int diamondEXP = score->m_diamonds * DIAMOND_EXP; - int secretCoinEXP = score->m_secretCoins * GOLD_COIN_EXP; - int userCoinEXP = score->m_userCoins * USER_COIN_EXP; - int demonEXP = score->m_demons * DEMON_EXP; - int cpEXP = score->m_creatorPoints * CP_EXP; - - if (std::max({starEXP, moonEXP, diamondEXP, secretCoinEXP, userCoinEXP, demonEXP, cpEXP}) == starEXP) - return CCSprite::createWithSpriteFrameName("GJ_starsIcon_001.png"); - if (std::max({starEXP, moonEXP, diamondEXP, secretCoinEXP, userCoinEXP, demonEXP, cpEXP}) == moonEXP) - return CCSprite::createWithSpriteFrameName("GJ_moonsIcon_001.png"); - if (std::max({starEXP, moonEXP, diamondEXP, secretCoinEXP, userCoinEXP, demonEXP, cpEXP}) == diamondEXP) - return CCSprite::createWithSpriteFrameName("GJ_diamondsIcon_001.png"); - if (std::max({starEXP, moonEXP, diamondEXP, secretCoinEXP, userCoinEXP, demonEXP, cpEXP}) == secretCoinEXP) - return CCSprite::createWithSpriteFrameName("GJ_coinsIcon_001.png"); - if (std::max({starEXP, moonEXP, diamondEXP, secretCoinEXP, userCoinEXP, demonEXP, cpEXP}) == userCoinEXP) - return CCSprite::createWithSpriteFrameName("GJ_coinsIcon2_001.png"); - if (std::max({starEXP, moonEXP, diamondEXP, secretCoinEXP, userCoinEXP, demonEXP, cpEXP}) == demonEXP) - return CCSprite::createWithSpriteFrameName("GJ_demonIcon_001.png"); - if (std::max({starEXP, moonEXP, diamondEXP, secretCoinEXP, userCoinEXP, demonEXP, cpEXP}) == cpEXP) - return CCSprite::createWithSpriteFrameName("GJ_hammerIcon_001.png"); - return nullptr; - } - - inline static ccColor3B getColorFromLevel(int currentLevel) { - ccColor3B barColor = {0, 0, 0}; - if (currentLevel >= 0 && currentLevel <= 24) - barColor = { 156, 156, 156 }; - if (currentLevel >= 25 && currentLevel <= 49) - barColor = { 228, 228, 228 }; - if (currentLevel >= 50 && currentLevel <= 74) - barColor = { 135, 255, 145 }; - if (currentLevel >= 75 && currentLevel <= 99) - barColor = { 83, 166, 255 }; - if (currentLevel >= 100 && currentLevel <= 124) - barColor = { 234, 117, 255 }; - if (currentLevel >= 125 && currentLevel <= 149) - barColor = { 255, 117, 177 }; - if (currentLevel >= 150 && currentLevel <= 174) - barColor = { 255, 156, 117 }; - if (currentLevel >= 175 && currentLevel <= 199) - barColor = { 255, 238, 106 }; - if (currentLevel >= 200 && currentLevel <= 224) - barColor = { 255, 0, 89 }; - if (currentLevel >= 225 && currentLevel <= 249) - barColor = { 145, 255, 0 }; - if (currentLevel >= 250 && currentLevel <= 274) - barColor = { 0, 255, 255 }; - if (currentLevel >= 275) - barColor = { 247, 0, 255 }; - if (currentLevel >= 300) { - barColor = {255, 150, 150}; - } - - return barColor; - } -}; diff --git a/src/MoreLeaderboards/MoreLeaderboards.cpp b/src/MoreLeaderboards/MoreLeaderboards.cpp deleted file mode 100644 index f34759a..0000000 --- a/src/MoreLeaderboards/MoreLeaderboards.cpp +++ /dev/null @@ -1,1295 +0,0 @@ -#include "MoreLeaderboards.h" -#include "Newtab.h" -#include -#include -#include - -StatsListType MoreLeaderboards::g_tab = StatsListType::Stars; -bool MoreLeaderboards::modFilter = false; -int MoreLeaderboards::modFilterType = 0; -std::string MoreLeaderboards::username = ""; -int MoreLeaderboards::scroll_int = 0; -static int page = 0; -static int start_count = 0; -static int end_count = 0; -static int total_count = 0; -std::string MoreLeaderboards::data_response_moreLB = ""; - -EventListener m_listener; - -std::vector MoreLeaderboards::getWords(std::string s, std::string delim) { - std::vector res; - std::string token = ""; - for (int i = 0; i < s.size(); i++) { - bool flag = true; - for (int j = 0; j < delim.size(); j++) { - if (s[i + j] != delim[j]) flag = false; - } - if (flag) { - if (token.size() > 0) { - res.push_back(token); - token = ""; - i += delim.size() - 1; - } - } else { - token += s[i]; - } - } - res.push_back(token); - return res; -} - - -class SearchUserLBLayer : public Popup { - protected: - bool setup(MoreLeaderboards* layer) { - m_layer = layer; - input_username->setMaxCharCount(20); - input_username->setPlaceholder(""); - input_username->setPositionY(10); - - m_buttonMenu->addChildAtPosition(input_username, Anchor::Center); - auto winSize = cocos2d::CCDirector::sharedDirector()->getWinSize(); - auto validate_spr = ButtonSprite::create("Search", 60, true, "bigFont.fnt", "GJ_button_01.png", 30, .5F); - auto validate_btn = CCMenuItemSpriteExtra::create( - validate_spr, - this, - menu_selector(SearchUserLBLayer::onValidate) - ); - m_buttonMenu->addChildAtPosition(validate_btn, Anchor::Center, {0, -35}); - - if (MoreLeaderboards::username != "") { - input_username->setString(MoreLeaderboards::username); - - auto delete_spr = CCSprite::createWithSpriteFrameName("GJ_deleteBtn_001.png"); - delete_spr->setScale(.45f); - auto delete_btn = CCMenuItemSpriteExtra::create( - delete_spr, - this, - menu_selector(SearchUserLBLayer::onRemoveUsername) - ); - m_buttonMenu->addChildAtPosition(delete_btn, Anchor::Right, {-17, 0}); - } - return true; - } - void onValidate(cocos2d::CCObject*); - void onRemoveUsername(cocos2d::CCObject*); - public: - MoreLeaderboards* m_layer; - TextInput* input_username = TextInput::create(200.0F, "Username", "bigFont.fnt"); - static SearchUserLBLayer* create(MoreLeaderboards* layer) { - auto ret = new SearchUserLBLayer(); - if (ret->initAnchored(260.f, 60.f, layer)) { - ret->autorelease(); - return ret; - } - delete ret; - return nullptr; - } -}; - -void SearchUserLBLayer::onValidate(CCObject* pSender) { - if (this->m_layer->loading) return; - - MoreLeaderboards::username = input_username->getString(); - - this->m_layer->changeTabPage(); - - this->m_layer->onTab(nullptr); - - Popup::onClose(pSender); -} - -void SearchUserLBLayer::onRemoveUsername(CCObject* pSender) { - MoreLeaderboards::username = ""; - MoreLeaderboards::scroll_int = 0; - input_username->setString(""); - - this->m_layer->changeTabPage(); - this->m_layer->onTab(nullptr); - - Popup::onClose(pSender); -} - -CCDictionary* MoreLeaderboards::responseToDict(const std::string& response){ - auto dict = CCDictionary::create(); - std::stringstream responseStream(response); - std::string currentKey; - std::string keyID; - std::string playerID; - std::string username; - std::string accountID; - - GameLevelManager* glm = GameLevelManager::sharedState(); - unsigned int i = 0; - while(getline(responseStream, currentKey, ':')){ - if(i % 2 == 0) { - keyID = currentKey; - } else { - if (keyID == "2") { // Player ID - playerID = currentKey; - } else if (keyID == "16") { - accountID = currentKey; - } else if (keyID == "1") { - username = currentKey; - } - dict->setObject(CCString::create(currentKey.c_str()),keyID); - } - i++; - } - if (playerID.length() > 0 && username.length() > 0 && accountID.length() > 0) { - glm->storeUserName(numFromString(playerID).unwrapOrDefault(), numFromString(accountID).unwrapOrDefault(), username); - } - return dict; -} - -void MoreLeaderboards::onMoreLeaderboards(CCObject* pSender) { - auto scene = CCScene::create(); - auto layer = MoreLeaderboards::create("more"); - scene->addChild(layer); - auto transitionFade = CCTransitionFade::create(0.5, scene); - CCDirector::sharedDirector()->pushScene(transitionFade); -} - -void MoreLeaderboards::onModsList(CCObject* pSender) { - auto scene = CCScene::create(); - auto layer = MoreLeaderboards::create("mods"); - scene->addChild(layer); - auto transitionFade = CCTransitionFade::create(0.5, scene); - CCDirector::sharedDirector()->pushScene(transitionFade); -} - -void MoreLeaderboards::onRegion(CCObject* pSender) { - SelectRegion::scene([this](std::string id) { - country_id = id; - - if (loading) return; - - loading = true; - - loading_circle = LoadingCircle::create(); - loading_circle->setZOrder(25); - loading_circle->setParentLayer(this); - loading_circle->show(); - - if (displayedData) { - displayedData->release(); - displayedData = cocos2d::CCArray::create(); - displayedData->retain(); - } - - page = 0; - - if (loading) { - startLoadingMore(); - loadPageMore(); - } - - resetInfos(); - }); - /*geode::createQuickPopup( - "Coming soon!", - R"text( -Filter by country leaderboards is coming soon on GDUtils! -Stay tuned for updates via our Discord server on the page of the mod in the Geode Index! - )text", - "OK", "Mod page", - [](auto, bool btn2) { - if (btn2) { - openIndexPopup(Mod::get()); - } - } - );*/ -} - -void MoreLeaderboards::onInfo(CCObject* pSender) { - FLAlertLayer::create( - nullptr, - "More Leaderboards", - R"text( -More Leaderboards is a feature that allows you to view more leaderboards than the ones in the game. -You can view leaderboards for Diamonds, User Coins, Demons, Moons, and Creators Points of people that are registered on Updated Leaderboards project. - -Thanks to ChiefWoof & the Helper team for providing the data for this feature! - )text", - "OK", - nullptr, - 400.0f - )->show(); -} - -void MoreLeaderboards::onLBInfo(CCObject* pSender) { - geode::createQuickPopup( - "Submit your user stats", - R"text( -You can submit your user stats to the Updated Leaderboards team by joining their Discord server and following the instructions right there. - )text", - "OK", "Discord Server", - [](auto, bool btn2) { - if (btn2) { - web::openLinkInBrowser("https://discord.gg/mZnDm886sR"); - } - } - ); -} - -MoreLeaderboards* MoreLeaderboards::create(std::string type) { - auto pRet = new MoreLeaderboards(); - SelectRegionCell::country_id = "NAN"; - if (pRet && pRet->init(type)) { - pRet->autorelease(); - return pRet; - } - CC_SAFE_DELETE(pRet); - return nullptr; -} - -bool MoreLeaderboards::init(std::string type) { - auto director = cocos2d::CCDirector::sharedDirector(); - auto size = director->getWinSize(); - - displayedData = cocos2d::CCArray::create(); - displayedData->retain(); - - auto background = CCSprite::create("GJ_gradientBG.png"); - auto backgroundSize = background->getContentSize(); - - background->setScaleX(size.width / backgroundSize.width); - background->setScaleY(size.height / backgroundSize.height); - background->setAnchorPoint({0, 0}); - background->setColor({0, 101, 253}); - background->setZOrder(-1); - this->addChild(background); - - // Corners - CCSprite* corner_left = CCSprite::createWithSpriteFrameName("GJ_sideArt_001.png"); - CCSprite* corner_right = CCSprite::createWithSpriteFrameName("GJ_sideArt_001.png"); - corner_right->setRotation(-90); - corner_left->setPosition({35, 35}); - corner_right->setPosition({size.width - 35, 35}); - this->addChild(corner_left); - this->addChild(corner_right); - - CCSprite* button = cocos2d::CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png"); - auto backButton = CCMenuItemSpriteExtra::create(button, this, menu_selector(MoreLeaderboards::backButton)); - CCMenu* menu = cocos2d::CCMenu::create(); - menu->addChild(backButton); - menu->setPosition({ 25, size.height - 25 }); - this->addChild(menu); - - if (type == "more") { - // Change region - auto menu_region = CCMenu::create(); - - auto regionSpr = CCSprite::create("earth_btn.png"_spr);; - regionSpr->setScale(.8f); - auto regionBtn = CCMenuItemSpriteExtra::create( - regionSpr, - this, - menu_selector(MoreLeaderboards::onRegion) - ); - regionBtn->setPosition(239, -52); - menu_region->addChild(regionBtn); - - auto infoSpr = cocos2d::CCSprite::createWithSpriteFrameName("GJ_infoIcon_001.png"); - auto infoBtn = CCMenuItemSpriteExtra::create( - infoSpr, - this, - menu_selector(MoreLeaderboards::onInfo) - ); - infoBtn->setPosition(-239, -120); - menu_region->addChild(infoBtn); - - auto lbSpr = cocos2d::CCSprite::createWithSpriteFrameName("GJ_levelLeaderboardBtn_001.png"); - auto lbBtn = CCMenuItemSpriteExtra::create( - lbSpr, - this, - menu_selector(MoreLeaderboards::onLBInfo) - ); - lbBtn->setPosition(-239, -57); - menu_region->addChild(lbBtn); - - this->addChild(menu_region); - - tab_page = 0; - - // tabs gradient - #ifndef GEODE_IS_IOS - m_tabsGradientNode = CCClippingNode::create(); - #else - m_tabsGradientNode = CCNode::create(); - #endif - m_tabsGradientNode->setContentSize(this->getContentSize()); - m_tabsGradientNode->setAnchorPoint({0.5f, 0.5f}); - m_tabsGradientNode->ignoreAnchorPointForPosition(true); - m_tabsGradientNode->setZOrder(0); - m_tabsGradientNode->setScale(0.8f); - #ifndef GEODE_IS_IOS - m_tabsGradientNode->setInverted(false); - m_tabsGradientNode->setAlphaThreshold(0.7f); - #endif - - m_tabsGradientSprite = CCSprite::create("tab-gradient.png"_spr); - m_tabsGradientNode->addChild(m_tabsGradientSprite); - - m_tabsGradientStencil = CCSprite::create("tab-gradient-mask.png"_spr); - m_tabsGradientStencil->setAnchorPoint({0.f, 0.f}); - m_tabsGradientStencil->setColor({172, 255, 67}); - m_tabsGradientStencil->setZOrder(1); - m_tabsGradientStencil->setScale(0.8f); - - #ifndef GEODE_IS_IOS - m_tabsGradientNode->setStencil(m_tabsGradientStencil); - #endif - - this->addChild(m_tabsGradientNode); - this->addChild(m_tabsGradientStencil); - - changeTabPage(); - - // select first tab - this->onTab(nullptr); - } else if (type == "mods") { - loading_circle = LoadingCircle::create(); - loading_circle->setZOrder(25); - loading_circle->setParentLayer(this); - loading_circle->show(); - - startLoadingMods(); - loadPageMods(); - } - setTouchEnabled(true); - setKeypadEnabled(true); - return true; -} - -void MoreLeaderboards::backButton(cocos2d::CCObject*) { - MoreLeaderboards::data_response_moreLB = ""; - MoreLeaderboards::g_tab = StatsListType::Stars; - MoreLeaderboards::username = ""; - MoreLeaderboards::scroll_int = 0; - MoreLeaderboards::modFilter = false; - MoreLeaderboards::modFilterType = 0; - cocos2d::CCDirector::sharedDirector()->popSceneWithTransition(0.5F, cocos2d::PopTransition::kPopTransitionFade); -}; - -void MoreLeaderboards::keyBackClicked() { - backButton(CCNode::create()); -} - -void MoreLeaderboards::fadeLoadingCircle() { - if (loading_circle == nullptr) return; - loading_circle->fadeAndRemove(); -}; - -void MoreLeaderboards::handle_request_mods(std::string const& data) { - if(!displayedData) { displayedData = CCArray::create(); displayedData->retain(); }; - if (data != "-1") { - displayedData = CCArray::create(); - - std::vector mods = getWords(data, "|"); - - while (mods.size() > 0) { - std::string mod = mods[0]; - CCDictionary* modDict = CCDictionary::create(); - modDict->setObject(cocos2d::CCString::create(mod), "modstring"); - displayedData->addObject(modDict); - mods.erase(mods.begin()); - }; - } - loadPageMods(); -} - -void MoreLeaderboards::startLoadingMods() { - const std::function then = [this](std::string const& data) { - handle_request_mods(data); - fadeLoadingCircle(); - }; - const std::function expect = [this](std::string const& error) { - fadeLoadingCircle(); - }; - - geode::utils::web::WebRequest request = web::WebRequest(); - m_listener.bind([expect = std::move(expect), then = std::move(then)](web::WebTask::Event* e) { - if (web::WebResponse* res = e->getValue()) { - if (res->ok()) { - then(res->string().unwrapOrDefault()); - } else { - expect("An error occured while sending a request on our server. Please try again later."); - } - } - }); - m_listener.setFilter(request.get("https://clarifygdps.com/gdutils/modslist.php")); -}; - -void MoreLeaderboards::loadPageMods() { - if(listLayer != nullptr) listLayer->removeFromParentAndCleanup(true); - - auto winSize = CCDirector::sharedDirector()->getWinSize(); - - leaderboardView = MoreLeaderboardsListView::create(displayedData, 356.f, 220.f); - listLayer = GJListLayer::create(leaderboardView, "GD Moderators", {191, 114, 62, 255}, 356.f, 220.f, 0); - listLayer->setPosition(winSize / 2 - listLayer->getScaledContentSize() / 2 - CCPoint(0,5)); - - addChild(listLayer); -} - -void MoreLeaderboards::startLoadingMore() { - geode::utils::web::WebRequest request = web::WebRequest(); - - this->retain(); - - const std::function expect = [this](std::string const& error) { - loading = false; - auto scene = CCDirector::sharedDirector()->getRunningScene(); - auto layer = scene->getChildren()->objectAtIndex(0); - if (layer == nullptr) return this->release(); - if (misc::getNodeName(layer) != "MoreLeaderboards") return this->release(); - geode::createQuickPopup( - "Error", - "An error occured while sending a request on our server. Please try again later.", - "OK", nullptr, - [this](auto, bool btn2) { - if (!btn2) { - MoreLeaderboards::g_tab = StatsListType::Stars; - keyBackClicked(); - } - } - ); - fadeLoadingCircle(); - loading = false; - this->release(); - }; - - const std::function then = [this](std::string const& data) { - if (data != "-1") { - data_region = data; - SelectRegion::displayedData = MoreLeaderboards::getWords(data, "|"); - } - - std::string type = ""; - geode::utils::web::WebRequest request = web::WebRequest(); - - switch (MoreLeaderboards::g_tab) { - case StatsListType::Diamonds: - type = "diamonds"; - break; - case StatsListType::UserCoins: - type = "ucoins"; - break; - case StatsListType::Demons: - type = "demons"; - break; - case StatsListType::Moons: - type = "moons"; - break; - case StatsListType::Creators: - type = "cp"; - break; - case StatsListType::Stars: - type = "stars"; - break; - case StatsListType::classicDemonsEasy: - type = "classicDemonsEasy"; - break; - case StatsListType::classicDemonsMedium: - type = "classicDemonsMedium"; - break; - case StatsListType::classicDemonsHard: - type = "classicDemonsHard"; - break; - case StatsListType::classicDemonsInsane: - type = "classicDemonsInsane"; - break; - case StatsListType::classicDemonsExtreme: - type = "classicDemonsExtreme"; - break; - case StatsListType::platformerDemonsEasy: - type = "platformerDemonsEasy"; - break; - case StatsListType::platformerDemonsMedium: - type = "platformerDemonsMedium"; - break; - case StatsListType::platformerDemonsHard: - type = "platformerDemonsHard"; - break; - case StatsListType::platformerDemonsInsane: - type = "platformerDemonsInsane"; - break; - case StatsListType::platformerDemonsExtreme: - type = "platformerDemonsExtreme"; - break; - case StatsListType::BetterProgression: - type = "betterProgression"; - break; - case StatsListType::Pointercrate: - type = "pointercratePoints"; - break; - } - - const std::function expect = [this](std::string const& error) { - loading = false; - - auto scene = CCDirector::sharedDirector()->getRunningScene(); - auto layer = scene->getChildren()->objectAtIndex(0); - if (layer == nullptr) return this->release(); - if (misc::getNodeName(layer) != "MoreLeaderboards") return this->release(); - geode::createQuickPopup( - "Error", - "An error occured while sending a request on our server. Please try again later.", - "OK", nullptr, - [this](auto, bool btn2) { - if (!btn2) { - MoreLeaderboards::g_tab = StatsListType::Stars; - keyBackClicked(); - } - } - ); - fadeLoadingCircle(); - loading = false; - this->release(); - }; - - const std::function then = [this](std::string const& data) { - loading = false; - - auto scene = CCDirector::sharedDirector()->getRunningScene(); - auto layer = scene->getChildren()->objectAtIndex(0); - if (layer == nullptr) return this->release(); - if (misc::getNodeName(layer) != "MoreLeaderboards") return this->release(); // prevent le crash, even though the layer shouldve already been destructed - if (data == "-1" || data.length() < 2) { - fadeLoadingCircle(); - geode::createQuickPopup( - "Error", - "An error occured while sending a request on our server. Please try again later.", - "OK", nullptr, - [this](auto, bool btn2) { - if (!btn2) { - MoreLeaderboards::g_tab = StatsListType::Stars; - keyBackClicked(); - } - } - ); - this->release(); - return; - } - if (data == "-2" || data.length() < 2) { - fadeLoadingCircle(); - FLAlertLayer::create(nullptr, - "Error", - "User not found : " + MoreLeaderboards::username, - "OK", - nullptr, - 200.0F - )->show(); - - MoreLeaderboards::scroll_int = 0; - this->release(); - - loadTabPageButtons(); - return; - } - - handle_request_more(data); - fadeLoadingCircle(); - loading = false; - - this->release(); - }; - - m_listener.bind([expect = std::move(expect), then = std::move(then)](web::WebTask::Event* e) { - if (web::WebResponse* response = e->getValue()) { - if (response->ok()) { - then(response->string().unwrap()); - } else { - expect("An error occurred while sending a request on our server. Please try again later."); - } - } - }); - - m_listener.setFilter( - request.param("type", type) - .param("page", page) - .param("country", country_id) - .param("username", username) - .param("mod", (modFilter ? "1" : "0")) - .param("modFilter", modFilterType) - .param("version", "1.0") - .get("https://clarifygdps.com/gdutils/moreleaderboards.php") - ); - }; - - if (data_region == "") { - m_listener.bind([expect = std::move(expect), then = std::move(then)] (web::WebTask::Event* e) { - if (web::WebResponse* res = e->getValue()) { - if (res->ok()) { - then(res->string().unwrap()); - } else { - expect("An error occured while sending a request on our server. Please try again later."); - } - } - }); - - m_listener.setFilter(request.get("https://clarifygdps.com/gdutils/moreleaderboards_region.php")); - } else { - then(data_region); - } -}; - -void MoreLeaderboards::handle_request_more(std::string const& data) { - if(!displayedData) { displayedData = CCArray::create(); displayedData->retain(); }; - - if (data != "-1") { - data_response_moreLB = data; - - displayedData = CCArray::create(); - std::vector dataString = getWords(data, "#"); - std::vector users = getWords(dataString[0], "|"); - std::vector data_page = getWords(dataString[1], "|"); - - while (users.size() > 0) { - std::string user = users[0]; - - auto score = GJUserScore::create( - MoreLeaderboards::responseToDict(user) - ); - displayedData->addObject(score); - users.erase(users.begin()); - }; - - int id = 0; - while (data_page.size() > 0) { - int page_test = numFromString(data_page[0]).unwrapOrDefault(); - - if (id == 0) { - start_count = page_test; - } else if (id == 1) { - end_count = page_test; - } else if (id == 2) { - total_count = page_test; - } else if (id == 3) { - page = page_test; - } else if (id == 4) { - if (page_test != 0) { - MoreLeaderboards::scroll_int = page_test; - } - } - - id++; - data_page.erase(data_page.begin()); - } - } - - loadPageMore(); - loadPageStats(); -} - -void MoreLeaderboards::loadPageMore() { - if(listLayer != nullptr) listLayer->removeFromParentAndCleanup(true); - - auto winSize = CCDirector::sharedDirector()->getWinSize(); - leaderboardViewScore = CustomListView::create(displayedData, nullptr, 220.f, 356.f, 0, BoomListType::Score, 0.0F); - listLayer = GJListLayer::create(leaderboardViewScore, nullptr, {191, 114, 62, 255}, 356.f, 220.f, 0); - listLayer->setZOrder(31); - listLayer->setPosition(winSize / 2 - listLayer->getScaledContentSize() / 2 - CCPoint(0,5)); - - addChild(listLayer); - - if (MoreLeaderboards::scroll_int != 0) { - listLayer->m_listView->m_tableView->scrollLayer((float)-INT_MAX); - listLayer->m_listView->m_tableView->scrollLayer(MoreLeaderboards::scroll_int); - } -} - -void MoreLeaderboards::onSearch(CCObject*) { - SearchUserLBLayer::create(this)->show(); -} - -void MoreLeaderboards::loadPageStats() { - auto scene = CCDirector::sharedDirector()->getRunningScene(); - auto winSize = CCDirector::sharedDirector()->getWinSize(); - - if (page_label != nullptr) page_label->removeFromParentAndCleanup(true); - if (this->getChildByIDRecursive("menu_label") != nullptr) this->getChildByIDRecursive("menu_label")->removeFromParentAndCleanup(true); - if (this->getChildByIDRecursive("menu_page") != nullptr) this->getChildByIDRecursive("menu_page")->removeFromParentAndCleanup(true); - - CCMenu* menu_label = CCMenu::create(); - menu_label->setID("menu_label"); - menu_label->setLayout( - RowLayout::create() - ->setAxisAlignment(AxisAlignment::Center) - ->setGap(10.f) - ); - menu_label->setPosition({ winSize.width / 2, 12.f }); - menu_label->setContentSize({ 300.f, 7.f }); - - std::string fmt = fmt::format("Top {} - {} of {}", start_count, end_count, total_count); - page_label = CCLabelBMFont::create(fmt.c_str(), "goldFont.fnt"); - page_label->setZOrder(40); - page_label->setLayoutOptions( - AxisLayoutOptions::create() - ->setAutoScale(true) - ->setScaleLimits(0, 0.7F) - ->setScalePriority(1) - ); - menu_label->addChild(page_label); - - trophy = CCSprite::createWithSpriteFrameName("rankIcon_top10_001.png"); - trophy->setScale(.3f); - trophy->setPosition(CCPoint { -5.f, 0.f } - page_label->getScaledContentSize().width); - menu_label->addChild(trophy); - - addChild(menu_label); - menu_label->updateLayout(); - - CCMenu* menu = CCMenu::create(); - menu->setID("menu_page"); - - if (page_left != nullptr) page_left->removeFromParentAndCleanup(true); - if (page_right != nullptr) page_right->removeFromParentAndCleanup(true); - - if (page > 0) { - page_left = CCMenuItemSpriteExtra::create( - CCSprite::createWithSpriteFrameName("GJ_arrow_02_001.png"), - this, - menu_selector(MoreLeaderboards::onPageLeft) - ); - page_left->setPosition(-220, 0); - menu->addChild(page_left); - } - - if (end_count < total_count) { - auto sprite = CCSprite::createWithSpriteFrameName("GJ_arrow_02_001.png"); - sprite->setFlipX(true); - page_right = CCMenuItemSpriteExtra::create( - sprite, - this, - menu_selector(MoreLeaderboards::onPageRight) - ); - page_right->setPosition(220, 0); - menu->addChild(page_right); - } - - addChild(menu); - - loadTabPageButtons(); -} - -void MoreLeaderboards::loadTabPageButtons() { - if (tab_page > 0) { - auto tab_page_left_sprite = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); - tab_page_left_sprite->setScale(0.6f); - tab_page_left = CCMenuItemSpriteExtra::create( - tab_page_left_sprite, - this, - menu_selector(MoreLeaderboards::onTabPageLeft) - ); - tab_page_left->setPosition(-184, 138); - m_menu->addChild(tab_page_left); - } - - if (tab_page < 2) { - auto tab_page_right_sprite = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); - tab_page_right_sprite->setScale(0.6f); - tab_page_right_sprite->setFlipX(true); - tab_page_right = CCMenuItemSpriteExtra::create( - tab_page_right_sprite, - this, - menu_selector(MoreLeaderboards::onTabPageRight) - ); - tab_page_right->setPosition(184, 138); - m_menu->addChild(tab_page_right); - } - - auto searchSpr = CCSprite::createWithSpriteFrameName("gj_findBtn_001.png"); - m_search = CCMenuItemSpriteExtra::create( - searchSpr, - this, - menu_selector(MoreLeaderboards::onSearch) - ); - m_search->setPosition(239, 104); - m_menu->addChild(m_search); - - auto mod_filter_btn_spr = CCSprite::createWithSpriteFrameName("modBadge_01_001.png"); - mod_filter_btn_spr->setScale(1.4f); - if (!modFilter) { - mod_filter_btn_spr->setColor({ 100, 100, 100 }); - } - mod_filter_btn = CCMenuItemSpriteExtra::create( - mod_filter_btn_spr, - this, - menu_selector(MoreLeaderboards::onModFilter) - ); - mod_filter_btn->setPosition(239.f, 69.f); - m_menu->addChild(mod_filter_btn); - - // Mod type filter - if (modFilter) { - CCSprite* mod_filter_type_spr; - CCSprite* mod_filter_type_spr1; - CCSprite* mod_filter_type_spr2; - CCSprite* mod_filter_type_spr3; - switch (modFilterType) { - case 0: - mod_filter_type_spr1 = CCSprite::createWithSpriteFrameName("modBadge_01_001.png"); - mod_filter_type_spr1->setScale(1.2f); - mod_filter_type_spr2 = CCSprite::createWithSpriteFrameName("modBadge_02_001.png"); - mod_filter_type_spr2->setScale(1.2f); - mod_filter_type_spr3 = CCSprite::createWithSpriteFrameName("modBadge_03_001.png"); - mod_filter_type_spr3->setScale(1.2f); - - mod_filter_type_spr1->setPosition({30, 21}); - mod_filter_type_spr2->setPosition({10, 21}); - mod_filter_type_spr3->setPosition({20, 11}); - - mod_filter_type_spr = CCSprite::create(); - mod_filter_type_spr->addChild(mod_filter_type_spr1); - mod_filter_type_spr->addChild(mod_filter_type_spr2); - mod_filter_type_spr->addChild(mod_filter_type_spr3); - mod_filter_type_spr->setContentSize({ 40, 40 }); - break; - case 1: - mod_filter_type_spr = CCSprite::createWithSpriteFrameName("modBadge_01_001.png"); - mod_filter_type_spr->setScale(1.4f); - break; - case 2: - mod_filter_type_spr = CCSprite::createWithSpriteFrameName("modBadge_02_001.png"); - mod_filter_type_spr->setScale(1.4f); - break; - case 3: - mod_filter_type_spr = CCSprite::createWithSpriteFrameName("modBadge_03_001.png"); - mod_filter_type_spr->setScale(1.4f); - break; - }; - - mod_filter_type_btn = CCMenuItemSpriteExtra::create( - mod_filter_type_spr, - this, - menu_selector(MoreLeaderboards::onModFilterType) - ); - mod_filter_type_btn->setPosition(239.f, 34.f); - m_menu->addChild(mod_filter_type_btn); - } -} - -void MoreLeaderboards::onTabPageLeft(CCObject* pSender) { - if (loading) return; - - tab_page--; - changeTabPage(); - - page = 0; - this->onTab(nullptr); -} - -void MoreLeaderboards::onTabPageRight(CCObject* pSender) { - if (loading) return; - - tab_page++; - changeTabPage(); - - page = 0; - this->onTab(nullptr); -} - -void MoreLeaderboards::onModFilter(CCObject* pSender) { - if (loading) return; - - modFilter = !modFilter; - modFilterType = 0; - - page = 0; - this->onTab(nullptr); -} - -void MoreLeaderboards::onModFilterType(CCObject* pSender) { - if (loading) return; - - if (modFilterType == 3) { - modFilterType = 0; - } else - modFilterType += 1; - - page = 0; - this->onTab(nullptr); -} - -void MoreLeaderboards::changeTabPage() { - if (m_search != nullptr) m_search->removeFromParentAndCleanup(true); - m_search = nullptr; - - if (m_tab1 != nullptr) m_tab1->removeFromParentAndCleanup(true); - if (m_tab2 != nullptr) m_tab2->removeFromParentAndCleanup(true); - if (m_tab3 != nullptr) m_tab3->removeFromParentAndCleanup(true); - if (m_tab4 != nullptr) m_tab4->removeFromParentAndCleanup(true); - if (m_tab5 != nullptr) m_tab5->removeFromParentAndCleanup(true); - if (m_tab6 != nullptr) m_tab6->removeFromParentAndCleanup(true); - - m_tab1 = nullptr; - m_tab2 = nullptr; - m_tab3 = nullptr; - m_tab4 = nullptr; - m_tab5 = nullptr; - m_tab6 = nullptr; - - if (this->getChildByIDRecursive("menu_gdutils_buttons") != nullptr) { - this->getChildByIDRecursive("menu_gdutils_buttons")->removeFromParentAndCleanup(true); - } - - m_menu = CCMenu::create(); - m_menu->setID("menu_gdutils_buttons"); - m_menu->setZOrder(1); - - auto stars_sprite = CCSprite::createWithSpriteFrameName("star_small01_001.png"); - auto moons_sprite = CCSprite::createWithSpriteFrameName("moon_small01_001.png"); - auto diamond_sprite = CCSprite::createWithSpriteFrameName("diamond_small01_001.png"); - auto usercoins_sprite = CCSprite::createWithSpriteFrameName("GJ_coinsIcon2_001.png"); - auto demons_sprite = CCSprite::createWithSpriteFrameName("GJ_demonIcon_001.png"); - auto creators_sprite = CCSprite::createWithSpriteFrameName("GJ_hammerIcon_001.png"); - - auto classic_sprite = CCSprite::createWithSpriteFrameName("star_small01_001.png"); - classic_sprite->setPositionX(30); - classic_sprite->setScale(1.2f); - - auto platformer_sprite = CCSprite::createWithSpriteFrameName("moon_small01_001.png"); - platformer_sprite->setPositionX(30); - platformer_sprite->setScale(1.2f); - - auto better_progression = CCSprite::create("better_progression.png"_spr); - auto pointercrate = CCSprite::createWithSpriteFrameName("diffIcon_06_btn_001.png"); - auto pointercrate_text = CCLabelBMFont::create("PC", "goldFont.fnt"); - pointercrate_text->setPosition(28, 0); - pointercrate_text->setScale(0.5f); - pointercrate->addChild(pointercrate_text); - - auto easydemon_sprite_classic = CCSprite::createWithSpriteFrameName("diffIcon_07_btn_001.png"); - easydemon_sprite_classic->addChild(classic_sprite); - auto mediumdemon_sprite_classic = CCSprite::createWithSpriteFrameName("diffIcon_08_btn_001.png"); - mediumdemon_sprite_classic->addChild(classic_sprite); - auto harddemon_sprite_classic = CCSprite::createWithSpriteFrameName("diffIcon_06_btn_001.png"); - harddemon_sprite_classic->addChild(classic_sprite); - auto insane_sprite_classic = CCSprite::createWithSpriteFrameName("diffIcon_09_btn_001.png"); - insane_sprite_classic->addChild(classic_sprite); - auto extreme_sprite_classic = CCSprite::createWithSpriteFrameName("diffIcon_10_btn_001.png"); - extreme_sprite_classic->addChild(classic_sprite); - - auto easydemon_sprite_platformer = CCSprite::createWithSpriteFrameName("diffIcon_07_btn_001.png"); - easydemon_sprite_platformer->addChild(platformer_sprite); - auto mediumdemon_sprite_platformer = CCSprite::createWithSpriteFrameName("diffIcon_08_btn_001.png"); - mediumdemon_sprite_platformer->addChild(platformer_sprite); - auto harddemon_sprite_platformer = CCSprite::createWithSpriteFrameName("diffIcon_06_btn_001.png"); - harddemon_sprite_platformer->addChild(platformer_sprite); - auto insane_sprite_platformer = CCSprite::createWithSpriteFrameName("diffIcon_09_btn_001.png"); - insane_sprite_platformer->addChild(platformer_sprite); - auto extreme_sprite_platformer = CCSprite::createWithSpriteFrameName("diffIcon_10_btn_001.png"); - extreme_sprite_platformer->addChild(platformer_sprite); - - switch (tab_page) { - case 0: - MoreLeaderboards::g_tab = StatsListType::Stars; - - m_tab1 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, stars_sprite, this, menu_selector(MoreLeaderboards::onTab)); - m_tab1->setPosition(-140.f, 132); - m_tab1->setTag(static_cast(StatsListType::Stars)); - m_tab1->setZOrder(30); - m_tab1->setScale(0.8f); - m_menu->addChild(m_tab1); - - m_tab2 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, moons_sprite, this, menu_selector(MoreLeaderboards::onTab)); - m_tab2->setPosition(-86.f, 132); - m_tab2->setTag(static_cast(StatsListType::Moons)); - m_tab2->setZOrder(30); - m_tab2->setScale(0.8f); - m_menu->addChild(m_tab2); - - m_tab3 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, usercoins_sprite, this, menu_selector(MoreLeaderboards::onTab)); - m_tab3->setPosition(-30.f, 132); - m_tab3->setTag(static_cast(StatsListType::UserCoins)); - m_tab3->setZOrder(30); - m_tab3->setScale(0.8f); - m_menu->addChild(m_tab3); - - m_tab4 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, demons_sprite, this, menu_selector(MoreLeaderboards::onTab)); - m_tab4->setPosition(26.f, 132); - m_tab4->setTag(static_cast(StatsListType::Demons)); - m_tab4->setZOrder(30); - m_tab4->setScale(0.8f); - m_menu->addChild(m_tab4); - - m_tab5 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, diamond_sprite, this, menu_selector(MoreLeaderboards::onTab)); - m_tab5->setPosition(82.f, 132); - m_tab5->setTag(static_cast(StatsListType::Diamonds)); - m_tab5->setZOrder(30); - m_tab5->setScale(0.8f); - m_menu->addChild(m_tab5); - - m_tab6 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, creators_sprite, this, menu_selector(MoreLeaderboards::onTab)); - m_tab6->setPosition(138.f, 132); - m_tab6->setTag(static_cast(StatsListType::Creators)); - m_tab6->setZOrder(30); - m_tab6->setScale(0.8f); - m_menu->addChild(m_tab6); - - break; - case 1: - if (geode::Loader::get()->isModLoaded("itzkiba.better_progression")) { - MoreLeaderboards::g_tab = StatsListType::BetterProgression; - - m_tab1 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, better_progression, this, menu_selector(MoreLeaderboards::onTab)); - m_tab1->setPosition(-140.f, 132); - m_tab1->setTag(static_cast(StatsListType::BetterProgression)); - m_tab1->setZOrder(30); - m_tab1->setScale(0.8f); - m_menu->addChild(m_tab1); - } else { - MoreLeaderboards::g_tab = StatsListType::Pointercrate; - - m_tab1 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, pointercrate, this, menu_selector(MoreLeaderboards::onTab)); - m_tab1->setPosition(-140.f, 132); - m_tab1->setTag(static_cast(StatsListType::Pointercrate)); - m_tab1->setZOrder(30); - m_tab1->setScale(0.8f); - m_menu->addChild(m_tab1); - } - - m_tab2 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, easydemon_sprite_classic, this, menu_selector(MoreLeaderboards::onTab)); - m_tab2->setPosition(-86.f, 132); - m_tab2->setTag(static_cast(StatsListType::classicDemonsEasy)); - m_tab2->setZOrder(30); - m_tab2->setScale(0.8f); - m_menu->addChild(m_tab2); - - m_tab3 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, mediumdemon_sprite_classic, this, menu_selector(MoreLeaderboards::onTab)); - m_tab3->setPosition(-30.f, 132); - m_tab3->setTag(static_cast(StatsListType::classicDemonsMedium)); - m_tab3->setZOrder(30); - m_tab3->setScale(0.8f); - m_menu->addChild(m_tab3); - - m_tab4 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, harddemon_sprite_classic, this, menu_selector(MoreLeaderboards::onTab)); - m_tab4->setPosition(26.f, 132); - m_tab4->setTag(static_cast(StatsListType::classicDemonsHard)); - m_tab4->setZOrder(30); - m_tab4->setScale(0.8f); - m_menu->addChild(m_tab4); - - m_tab5 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, insane_sprite_classic, this, menu_selector(MoreLeaderboards::onTab)); - m_tab5->setPosition(82.f, 132); - m_tab5->setTag(static_cast(StatsListType::classicDemonsInsane)); - m_tab5->setZOrder(30); - m_tab5->setScale(0.8f); - m_menu->addChild(m_tab5); - - m_tab6 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, extreme_sprite_classic, this, menu_selector(MoreLeaderboards::onTab)); - m_tab6->setPosition(138.f, 132); - m_tab6->setTag(static_cast(StatsListType::classicDemonsExtreme)); - m_tab6->setZOrder(30); - m_tab6->setScale(0.8f); - m_menu->addChild(m_tab6); - - break; - case 2: - MoreLeaderboards::g_tab = StatsListType::platformerDemonsEasy; - - m_tab1 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, easydemon_sprite_platformer, this, menu_selector(MoreLeaderboards::onTab)); - m_tab1->setPosition(-140.f, 132); - m_tab1->setTag(static_cast(StatsListType::platformerDemonsEasy)); - m_tab1->setZOrder(30); - m_tab1->setScale(0.8f); - m_menu->addChild(m_tab1); - - m_tab2 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, mediumdemon_sprite_platformer, this, menu_selector(MoreLeaderboards::onTab)); - m_tab2->setPosition(-86.f, 132); - m_tab2->setTag(static_cast(StatsListType::platformerDemonsMedium)); - m_tab2->setZOrder(30); - m_tab2->setScale(0.8f); - m_menu->addChild(m_tab2); - - m_tab3 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, harddemon_sprite_platformer, this, menu_selector(MoreLeaderboards::onTab)); - m_tab3->setPosition(-30.f, 132); - m_tab3->setTag(static_cast(StatsListType::platformerDemonsHard)); - m_tab3->setZOrder(30); - m_tab3->setScale(0.8f); - m_menu->addChild(m_tab3); - - m_tab4 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, insane_sprite_platformer, this, menu_selector(MoreLeaderboards::onTab)); - m_tab4->setPosition(26.f, 132); - m_tab4->setTag(static_cast(StatsListType::platformerDemonsInsane)); - m_tab4->setZOrder(30); - m_tab4->setScale(0.8f); - m_menu->addChild(m_tab4); - - m_tab5 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, extreme_sprite_platformer, this, menu_selector(MoreLeaderboards::onTab)); - m_tab5->setPosition(82.f, 132); - m_tab5->setTag(static_cast(StatsListType::platformerDemonsExtreme)); - m_tab5->setZOrder(30); - m_tab5->setScale(0.8f); - m_menu->addChild(m_tab5); - - if (geode::Loader::get()->isModLoaded("itzkiba.better_progression")) { - m_tab6 = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, pointercrate, this, menu_selector(MoreLeaderboards::onTab)); - m_tab6->setPosition(138.f, 132); - m_tab6->setTag(static_cast(StatsListType::Pointercrate)); - m_tab6->setZOrder(30); - m_tab6->setScale(0.8f); - m_menu->addChild(m_tab6); - } - - break; - } - - this->addChild(m_menu); -} - -void MoreLeaderboards::onPageLeft(CCObject* pSender) { - if (loading) return; - - MoreLeaderboards::username = ""; - MoreLeaderboards::scroll_int = 0; - - loading = true; - - loading_circle = LoadingCircle::create(); - loading_circle->setParentLayer(this); - loading_circle->setZOrder(25); - loading_circle->show(); - - if (displayedData) { - displayedData->release(); - displayedData = cocos2d::CCArray::create(); - displayedData->retain(); - } - - page--; - resetInfos(); - - if (loading) { - startLoadingMore(); - loadPageMore(); - } -} - -void MoreLeaderboards::onPageRight(CCObject* pSender) { - if (loading) return; - - MoreLeaderboards::username = ""; - MoreLeaderboards::scroll_int = 0; - - loading = true; - - loading_circle = LoadingCircle::create(); - loading_circle->setZOrder(25); - loading_circle->setParentLayer(this); - loading_circle->show(); - - if (displayedData) { - displayedData->release(); - displayedData = cocos2d::CCArray::create(); - displayedData->retain(); - } - - page++; - resetInfos(); - - if (loading) { - startLoadingMore(); - loadPageMore(); - } -} - -void MoreLeaderboards::resetInfos() { - if (page_label != nullptr) page_label->removeFromParentAndCleanup(true); - if (page_left != nullptr) page_left->removeFromParentAndCleanup(true); - if (page_right != nullptr) page_right->removeFromParentAndCleanup(true); - if (trophy != nullptr) trophy->removeFromParentAndCleanup(true); - if (mod_filter_btn != nullptr) mod_filter_btn->removeFromParentAndCleanup(true); - if (mod_filter_type_btn != nullptr) mod_filter_type_btn->removeFromParentAndCleanup(true); - - page_label = nullptr; - page_left = nullptr; - page_right = nullptr; - trophy = nullptr; - mod_filter_btn = nullptr; - mod_filter_type_btn = nullptr; -} - -void MoreLeaderboards::onTab(CCObject* pSender) { - if (loading) return; - - loading = true; - - loading_circle = LoadingCircle::create(); - loading_circle->setZOrder(25); - loading_circle->setParentLayer(this); - loading_circle->show(); - - if (displayedData) { - displayedData->release(); - displayedData = cocos2d::CCArray::create(); - displayedData->retain(); - } - - if (pSender) { - MoreLeaderboards::g_tab = static_cast(pSender->getTag()); - } - resetInfos(); - - page = 0; - - auto toggleTab = [this](CCMenuItemToggler* member) -> void { - auto isSelected = member->getTag() == static_cast(MoreLeaderboards::g_tab); - auto targetMenu = m_menu; - member->toggle(isSelected); - if (member->getParent() != targetMenu) { - member->retain(); - member->removeFromParent(); - targetMenu->addChild(member); - member->release(); - } - if (isSelected && m_tabsGradientStencil) - m_tabsGradientStencil->setPosition(member->m_onButton->convertToWorldSpace({0.f, 0.f})); - }; - - if (m_tab1 != nullptr) toggleTab(m_tab1); - if (m_tab2 != nullptr) toggleTab(m_tab2); - if (m_tab3 != nullptr) toggleTab(m_tab3); - if (m_tab4 != nullptr) toggleTab(m_tab4); - if (m_tab5 != nullptr) toggleTab(m_tab5); - if (m_tab6 != nullptr) toggleTab(m_tab6); - - if (loading) { - startLoadingMore(); - loadPageMore(); - } -} - -class $modify(LeaderboardsLayer) { - bool init(LeaderboardState state) { - if (!LeaderboardsLayer::init(state)) return false; - auto menu = CCMenu::create(); - - auto plusSpr = CCSprite::createWithSpriteFrameName("GJ_plusBtn_001.png"); - plusSpr->setScale(.8f); - auto plusBtn = CCMenuItemSpriteExtra::create( - plusSpr, - this, - menu_selector(MoreLeaderboards::onMoreLeaderboards) - ); - plusBtn->setPosition(239, 20); - menu->addChild(plusBtn); - - auto modsSpr = CCSprite::createWithSpriteFrameName("modBadge_01_001.png"); - modsSpr->setScale(1.5f); - auto modsBtn = CCMenuItemSpriteExtra::create( - modsSpr, - this, - menu_selector(MoreLeaderboards::onModsList) - ); - modsBtn->setPosition(239, -24); - menu->addChild(modsBtn); - - this->addChild(menu); - - return true; - } -}; diff --git a/src/MoreLeaderboards/MoreLeaderboards.h b/src/MoreLeaderboards/MoreLeaderboards.h deleted file mode 100644 index ead95df..0000000 --- a/src/MoreLeaderboards/MoreLeaderboards.h +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once -#include "../includes.h" -#include -#include "MoreLeaderboardsListView.h" -#include "SelectRegion.h" - -#include -#include - -enum class StatsListType { - Stars, - Diamonds, - UserCoins, - Demons, - Moons, - Creators, - classicDemonsEasy, - classicDemonsMedium, - classicDemonsHard, - classicDemonsInsane, - classicDemonsExtreme, - platformerDemonsEasy, - platformerDemonsMedium, - platformerDemonsHard, - platformerDemonsInsane, - platformerDemonsExtreme, - BetterProgression, - Pointercrate -}; - -class MoreLeaderboards : public CCLayer { - MoreLeaderboardsListView* leaderboardView = nullptr; - CustomListView* leaderboardViewScore = nullptr; - GJListLayer* listLayer = nullptr; - LoadingCircle* loading_circle = nullptr; - cocos2d::CCArray* displayedData; - - CCLabelBMFont* page_label = nullptr; - CCMenuItemSpriteExtra* page_left = nullptr; - CCMenuItemSpriteExtra* page_right = nullptr; - CCMenuItemSpriteExtra* tab_page_left = nullptr; - CCMenuItemSpriteExtra* tab_page_right = nullptr; - CCMenuItemSpriteExtra* mod_filter_btn = nullptr; - CCMenuItemSpriteExtra* mod_filter_type_btn = nullptr; - CCSprite* trophy = nullptr; - - CCString* datas = nullptr; - std::string data_region = ""; - - std::string country_id = "NAN"; - - CCMenu* m_menu; - CCMenuItemToggler* m_tab1; - CCMenuItemToggler* m_tab2; - CCMenuItemToggler* m_tab3; - CCMenuItemToggler* m_tab4; - CCMenuItemToggler* m_tab5; - CCMenuItemToggler* m_tab6; - int tab_page = 0; - - CCMenuItemSpriteExtra* m_search; - - #ifndef GEODE_IS_IOS - CCClippingNode* m_tabsGradientNode = nullptr; - #else - CCNode* m_tabsGradientNode = nullptr; - #endif - CCSprite* m_tabsGradientSprite = nullptr; - CCSprite* m_tabsGradientStencil = nullptr; - - protected: - virtual bool init(std::string type); - virtual void keyBackClicked(); - void startLoadingMods(); - void loadPageMods(); - void startLoadingMore(); - void loadPageMore(); - void loadPageStats(); - - void resetInfos(); - public: - static std::string data_response_moreLB; - static StatsListType g_tab; - static std::string username; - static int scroll_int; - static bool modFilter; - static int modFilterType; - bool loading = false; - - EventListener m_listener; - - void onMoreLeaderboards(CCObject*); - void onModsList(CCObject*); - void onRegion(CCObject*); - void onInfo(CCObject*); - void onLBInfo(CCObject*); - - void onTab(CCObject* pSender); - void onPageLeft(CCObject* pSender); - void onPageRight(CCObject* pSender); - - void loadTabPageButtons(); - void onTabPageLeft(CCObject* pSender); - void onTabPageRight(CCObject* pSender); - void onModFilter(CCObject* pSender); - void onModFilterType(CCObject* pSender); - void changeTabPage(); - - void onSearch(CCObject*); - - static MoreLeaderboards* create(std::string type); - void fadeLoadingCircle(); - void handle_request_mods(std::string const& data); - void handle_request_more(std::string const& data); - - static std::vector getWords(std::string s, std::string delim); - static CCDictionary* responseToDict(const std::string& response); - - void backButton(CCObject*); -}; diff --git a/src/MoreLeaderboards/MoreLeaderboardsListView.h b/src/MoreLeaderboards/MoreLeaderboardsListView.h deleted file mode 100644 index dfea057..0000000 --- a/src/MoreLeaderboards/MoreLeaderboardsListView.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include - -using namespace geode::prelude; - -class MoreLeaderboardsListView : public CustomListView { - protected: - void setupList(float) override; - TableViewCell* getListCell(const char* key) override; - void loadCell(TableViewCell* cell, int index) override; - static CCRect calculateNodeCoverage(CCArray* nodes); - public: - static MoreLeaderboardsListView* create(CCArray* levels, float width, float height); -}; diff --git a/src/MoreLeaderboards/Newtab.h b/src/MoreLeaderboards/Newtab.h deleted file mode 100644 index b5e4c31..0000000 --- a/src/MoreLeaderboards/Newtab.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once -#include "../includes.h" - -class NewTabButton : public CCMenuItemToggler { - public: - static NewTabButton* create( - TabBaseColor unselected, TabBaseColor selected, CCNode* icon, - cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback - ); -}; - -class NewBasedButtonSprite : public cocos2d::CCSprite { - protected: - BaseType m_type; - int m_size; - int m_color; - cocos2d::CCNode* m_onTop = nullptr; - float m_onTopRelativeScale = 1.3f; - cocos2d::CCPoint m_topOffset = cocos2d::CCPointZero; - - bool init(cocos2d::CCNode* ontop, BaseType type, int size, int color); - bool initWithSprite( - const char* sprName, float sprScale, BaseType type, int size, int color - ); - bool initWithSpriteFrameName( - const char* sprName, float sprScale, BaseType type, int size, int color - ); - - virtual cocos2d::CCSize getMaxTopSize() const; - - virtual ~NewBasedButtonSprite(); - - public: - /** - * Create a BasedButtonSprite. In general, it is recommended to use - * the specialized subclasses, such as CircleButtonSprite or - * TabButtonSprite - * @param ontop The top node of the sprite - * @param type The type of the base sprite - * @param size The size of the base sprite. Cast this from the base - * type's respective BaseSize enum - * @param color The color of the base sprite. Cast this from the base - * type's respective BaseColor enum - * @returns Created BasedButtonSprite, or nullptr if parameters were - * invalid - */ - static NewBasedButtonSprite* create( - cocos2d::CCNode* ontop, BaseType type, int size, int color - ); - - /** - * Set an offset to the top sprite - */ - void setTopOffset(cocos2d::CCPoint const& offset); - void setTopRelativeScale(float scale); - - cocos2d::CCNode* getTopNode() const; -}; - -class NewTabButtonSprite : public NewBasedButtonSprite { - public: - static NewTabButtonSprite* create( - CCNode* icon, - TabBaseColor color, - TabBaseSize size = TabBaseSize::Normal - ); -}; \ No newline at end of file diff --git a/src/MoreLeaderboards/SelectRegion.h b/src/MoreLeaderboards/SelectRegion.h deleted file mode 100644 index 84c5873..0000000 --- a/src/MoreLeaderboards/SelectRegion.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "../includes.h" -#include -#include "SelectRegionCell.h" -#include "../OldBorder.hpp" - -class SelectRegion : public Popup<> { - LoadingCircle* loading_circle; - std::function selectedRegion; - - protected: - bool setup() override; - void loadPage(); - - cocos2d::CCSize m_sScrLayerSize; - public: - static std::vector displayedData; - - SelectRegion(const std::function& callback) : selectedRegion(callback) {} - - static void scene(const std::function& callback); - - static std::vector getWords(std::string s, std::string delim); -}; \ No newline at end of file diff --git a/src/Notifications/DailyChest.cpp b/src/Notifications/DailyChest.cpp deleted file mode 100644 index 5a968c9..0000000 --- a/src/Notifications/DailyChest.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "DailyChest.h" -#include "EventsPush.h" - -static GJRewardItem* time1 = nullptr; -static GJRewardItem* time2 = nullptr; - -void DailyChest::getRewards(unsigned int type) { - auto glm = GameLevelManager::sharedState(); - if (glm) { - glm->m_GJRewardDelegate = this; - glm->getGJRewards(0); - } -}; - -void DailyChest::rewardsStatusFinished(int p0) { - GameStatsManager* gsm; - // Check if rewards are loaded - gsm = GameStatsManager::sharedState(); - if (gsm->m_rewardItems->count() == 0) return; - - // Get the rewards - int time1_value = 0x1; - int time2_value = 0x2; - time1 = typeinfo_cast(gsm->m_rewardItems->objectForKey(time1_value)); - time2 = typeinfo_cast(gsm->m_rewardItems->objectForKey(time2_value)); - - EventData data; - data.sprite = "GJ_square04.png"; - data.level_name = " "; - data.level_creator = " "; - if (time1 != nullptr) { - if (time1->m_timeRemaining == 0) { - data.type = EventType::smallChest; - data.title = "Small Daily Chest available!"; - EventsPush::pushRateLevel(CCDirector::sharedDirector()->getRunningScene(), data); - } - } - - if (time2 != nullptr) { - if (time2->m_timeRemaining == 0) { - data.type = EventType::largeChest; - data.title = "Big Daily Chest available!"; - EventsPush::pushRateLevel(CCDirector::sharedDirector()->getRunningScene(), data); - } - } -}; - -void DailyChest::rewardsStatusFailed() { - log::error("Failed to get rewards"); -}; diff --git a/src/Notifications/EventsPush.cpp b/src/Notifications/EventsPush.cpp deleted file mode 100644 index 07df09f..0000000 --- a/src/Notifications/EventsPush.cpp +++ /dev/null @@ -1,916 +0,0 @@ -#include "EventsPush.h" -#include "../Settings/CustomSettings.hpp" -#include "DailyChest.h" -#include "Geode/utils/general.hpp" -#include -#include -#include - -static std::unordered_map RUNNING_REQUESTS {}; -static std::mutex lock_var; -const std::lock_guard lock(lock_var); - -std::vector EventsPush::getWords(std::string s, std::string delim) { - std::vector res; - std::string token = ""; - for (int i = 0; i < s.size(); i++) { - bool flag = true; - for (int j = 0; j < delim.size(); j++) { - if (s[i + j] != delim[j]) flag = false; - } - if (flag) { - if (token.size() > 0) { - res.push_back(token); - token = ""; - i += delim.size() - 1; - } - } else { - token += s[i]; - } - } - res.push_back(token); - return res; -} - -std::queue eventQueue; -bool processingEvents = false; -int zOrder = 200; -EventsPush* EventsPush::create(EventData data) { - auto ret = new EventsPush(); - if (ret && ret->init(data)) { - ret->autorelease(); - return ret; - } - CC_SAFE_DELETE(ret); - return nullptr; -} - -const char* getDemonDifficultyIcon(int stars) { - switch(stars){ - case 3: - return "difficulty_07_btn_001.png"; - case 4: - return "difficulty_08_btn_001.png"; - case 5: - return "difficulty_09_btn_001.png"; - case 6: - return "difficulty_10_btn_001.png"; - default: - return "difficulty_06_btn_001.png"; - } -} - -const char* getDifficultyIcon(int stars) { - switch(stars){ - case 10: - return "difficulty_01_btn_001.png"; - case 20: - return "difficulty_02_btn_001.png"; - case 30: - return "difficulty_03_btn_001.png"; - case 40: - return "difficulty_04_btn_001.png"; - case 50: - return "difficulty_05_btn_001.png"; - case 60: - return "difficulty_auto_btn_001.png"; - default: - return "difficulty_00_btn_001.png"; - } -} - -void EventsPush::destroySelf() { - auto scene = CCDirector::sharedDirector()->getRunningScene(); - auto layer = reinterpret_cast(scene->getChildByTag(1932)); - if (layer != nullptr) { - scene->removeChildByTag(1932); - } - EventsPush::eventCompletedCallback(scene); -} -// stole from GDR mod lol -GJDifficulty getDifficulty(int stars) { - switch(stars){ - case 0: - return GJDifficulty::NA; - case 10: - return GJDifficulty::Easy; - case 20: - return GJDifficulty::Normal; - case 30: - return GJDifficulty::Hard; - case 40: - return GJDifficulty::Harder; - case 50: - return GJDifficulty::Insane; - case 60: - return GJDifficulty::Auto; - default: - return GJDifficulty::NA; - } -} - -GJDifficulty getDemonDifficulty(int stars) { - switch(stars){ - case 3: - return GJDifficulty::DemonEasy; - case 4: - return GJDifficulty::DemonMedium; - case 5: - return GJDifficulty::DemonInsane; - case 6: - return GJDifficulty::DemonExtreme; - default: - return GJDifficulty::Demon; - } -} - -std::vector split_str(std::string &string, char separator) { - std::stringstream segmentstream(string); - std::string segmented; - std::vector splitlist; - - while (std::getline(segmentstream, segmented, separator)) { - splitlist.push_back(segmented); - } - - return splitlist; -}; - -GJGameLevel* EventsPush::convertLevelToJSON(std::string& data) { - // Robtop to JSON - GJGameLevel* level = GJGameLevel::create(); -#ifdef GEODE_IS_WINDOWS - auto gamelevelmanager = GameLevelManager::sharedState(); - auto gamestatslevel = GameStatsManager::sharedState(); - - std::string auto_level = "0"; - std::string demon = "0"; - auto datas_list = split_str(data, '#'); - std::string level_data = datas_list[0]; - std::string creator_data = datas_list[1]; - - // Level data - auto level_data_list = split_str(level_data, ':'); - if (level_data_list[21] != "") { - demon = level_data_list[21]; // - } else { - demon = "0"; - } - if (level_data_list[25] != "") { - auto_level = level_data_list[25]; // - } else { - auto_level = "0"; - } - - level->m_levelID = numFromString(level_data_list[1]).unwrapOrDefault(); - - level->m_levelName = level_data_list[3]; - level->m_levelDesc = level_data_list[35]; - level->m_levelVersion = numFromString(level_data_list[5]).unwrapOrDefault(); - level->m_userID = numFromString(level_data_list[7]).unwrapOrDefault(); - - level->m_ratings = numFromString(level_data_list[9]).unwrapOrDefault(); - level->m_ratingsSum = numFromString(level_data_list[11]).unwrapOrDefault(); - - if (level_data_list[9] == "10") { - if (demon == "1") { - std::string levelDemonDifficultyStr = level_data_list[23]; - level->m_difficulty = getDemonDifficulty(numFromString(levelDemonDifficultyStr).unwrapOrDefault()); - } else { - if (auto_level == "1") { - level->m_difficulty = getDifficulty(0); - } else { - level->m_difficulty = getDifficulty(numFromString(level_data_list[11]).unwrapOrDefault()); - } - } - } - level->m_downloads = numFromString(level_data_list[13]).unwrapOrDefault(); - if (level_data_list[53] == "0") { - level->m_audioTrack = numFromString(level_data_list[15]).unwrapOrDefault(); - } else { - level->m_songID = numFromString(level_data_list[53]).unwrapOrDefault(); - } - - std::string levelGameVersionStr = level_data_list[17]; - level->m_gameVersion = numFromString(levelGameVersionStr).unwrapOrDefault(); - int levelLikes = numFromString(level_data_list[19]).unwrapOrDefault(); - if (levelLikes >= 0) { - level->m_likes = levelLikes; - level->m_dislikes = 0; - } else { - level->m_likes = 0; - level->m_dislikes = 0 - levelLikes; - } - level->m_levelLength = numFromString(level_data_list[37]).unwrapOrDefault(); - - level->m_demon = numFromString(demon).unwrapOrDefault(); - level->m_stars = numFromString(level_data_list[27]).unwrapOrDefault(); - - if (auto_level == "1") { - level->m_autoLevel = true; - } else { - level->m_autoLevel = false; - } - - level->m_originalLevel = numFromString(level_data_list[39]).unwrapOrDefault(); - if (level_data_list[41] == "1") { - level->m_twoPlayerMode = true; - } else { - level->m_twoPlayerMode = false; - } - - level->m_coins = numFromString(level_data_list[43]).unwrapOrDefault(); - level->m_coinsVerified = numFromString(level_data_list[45]).unwrapOrDefault(); - level->m_starsRequested = numFromString(level_data_list[47]).unwrapOrDefault(); - level->m_featured = numFromString(level_data_list[29]).unwrapOrDefault(); - if (level_data_list[31] == "1") { - level->m_isEpic = true; - } else { - level->m_isEpic = false; - } - level->m_demonDifficulty = numFromString(level_data_list[23]).unwrapOrDefault(); - - level->m_objectCount = numFromString(level_data_list[33]).unwrapOrDefault(); - - level->m_levelNotDownloaded = true; - - level->m_workingTime = numFromString(level_data_list[49]).unwrapOrDefault(); - - CCArray* levelids = gamelevelmanager->m_onlineLevels->allKeys(); - CCObject* obj; - CCARRAY_FOREACH(levelids, obj) { - std::string levelid = (static_cast(obj))->getCString(); - if (numFromString(levelid).unwrapOrDefault() == level->m_levelID) { - auto levelFromSaved = static_cast(gamelevelmanager->m_onlineLevels->objectForKey(levelid)); - level->m_normalPercent = levelFromSaved->m_normalPercent; - level->m_newNormalPercent2 = levelFromSaved->m_newNormalPercent2; - level->m_practicePercent = levelFromSaved->m_practicePercent; - level->m_levelFavorited = levelFromSaved->m_levelFavorited; - level->m_levelFolder = levelFromSaved->m_levelFolder; - level->m_attempts = levelFromSaved->m_attempts; - level->m_jumps = levelFromSaved->m_jumps; - level->m_clicks = levelFromSaved->m_clicks; - level->m_attemptTime = levelFromSaved->m_attemptTime; - - level->m_levelNotDownloaded = levelFromSaved->m_levelNotDownloaded; - level->m_chk = levelFromSaved->m_chk; - level->m_isChkValid = levelFromSaved->m_isChkValid; - level->m_isCompletionLegitimate = levelFromSaved->m_isCompletionLegitimate; - level->m_isVerified = levelFromSaved->m_isVerified; - level->m_isUploaded = levelFromSaved->m_isUploaded; - } - } - - // Creator data - auto creator_data_list = split_str(creator_data, ':'); - level->m_creatorName = creator_data_list[1]; - level->m_accountID = numFromString(creator_data_list[2]).unwrapOrDefault(); -#endif - return level; -} - -void EventsPush::onClickBtn(CCObject* ret) { - auto scene = CCDirector::sharedDirector()->getRunningScene(); - auto layer = scene->getChildren()->objectAtIndex(0); - if (layer == nullptr) return; - auto events_layer = reinterpret_cast(scene->getChildByTag(1932)); - if (events_layer == nullptr) return; - std::string layerName = typeid(*layer).name() + 6; - if (layerName != "PlayLayer" && layerName != "PauseLayer" && layerName != "LevelEditorLayer") { // redirect to level - if (eventType == EventType::Rate) { - if (events_layer->level->m_levelID == 0) return; - - std::string const& url = "http://www.boomlings.com/database/getGJLevels21.php"; - #ifndef GEODE_IS_MACOS - int level_id = events_layer->level->m_levelID.value(); - #else // mac os - int level_id = events_layer->levelId; - #endif - std::string const& fields = "secret=Wmfd2893gb7&type=0&str=" + std::to_string(level_id); - - geode::utils::web::WebRequest request = web::WebRequest(); - RUNNING_REQUESTS.emplace( - "@loaderEventRateNotification", - request.bodyString(fields).post(url).map( - [](web::WebResponse* response) { - if (response->ok()) { - if (response->data().empty()) { - FLAlertLayer::create(nullptr, - "Error", - "An server error happened.", - "OK", - nullptr, - 180.0F - )->show(); - } else { - auto data_result = response->string().unwrapOrDefault(); - if (data_result != "-1") { - auto scene = CCScene::create(); - auto layer = LevelInfoLayer::create(EventsPush::convertLevelToJSON(data_result), false); - layer->downloadLevel(); - scene->addChild(layer); - CCDirector::sharedDirector()->pushScene(cocos2d::CCTransitionFade::create(0.5f, scene)); - } else { - log::info("Level not found. (-1)"); - } - } - } else { - FLAlertLayer::create(nullptr, - "Error", - "An server error happened.", - "OK", - nullptr, - 180.0F - )->show(); - } - - RUNNING_REQUESTS.erase("@loaderEventRateNotification"); - return *response; - } - ) - ); - } else if (eventType == EventType::Daily) { - DailyLevelPage::create(GJTimedLevelType::Daily)->show(); - return; - } else if (eventType == EventType::Weekly) { - DailyLevelPage::create(GJTimedLevelType::Weekly)->show(); - return; - } else if (eventType == EventType::Event) { - DailyLevelPage::create(GJTimedLevelType::Event)->show(); - return; - } else if (eventType == EventType::List) { - if (events_layer->level->m_levelID == 0) return; - - GJSearchObject* search_obj = GJSearchObject::create(SearchType::Search, std::to_string(events_layer->level->m_levelID)); - search_obj->m_searchMode = 1; - LevelBrowserLayer::create(search_obj)->show(); - return; - } /*else if (eventType == EventType::smallChest) { - RewardsPage::create()->show(); - return; - }*/ - } else { // copy to clipboard - #ifndef GEODE_IS_MACOS - clipboard::write(std::to_string(events_layer->level->m_levelID)); - #else - clipboard::write(std::to_string(events_layer->levelId)); - #endif - } -} - -bool EventsPush::init(EventData data) { - auto scene = CCDirector::sharedDirector()->getRunningScene(); - // type - // 0 = new rate - // 1 = daily - // 2 = weekly - - // rate - // 0 = unrated / star rate - // 1 = featured - // 2 = epic - // {'demon': 0, 'type': 0, 'starsum': 20, 'stars': 2, 'rate': 2, 'title': 'New Rated Level !', 'level_name': 'Pourquoi', 'level_creator': 'by Jouca', 'sprite': 'GJ_square01.png'} - int starsum = data.starsum; - int stars = data.stars; - int rateType = data.rate; - int coins = data.coins; - int areCoinsVerified = data.verified_coins; - int level_id = 0; - if (data.level_id != -1) { - level_id = data.level_id; - level->m_levelName = data.level_name; - level->m_coins = coins; - level->m_coinsVerified = areCoinsVerified; - level->m_levelID = level_id; - #ifdef GEODE_IS_MACOS - this->levelId = level_id; - #endif - } - - - auto menu = CCMenu::create(); - - bool newRate = Mod::get()->template getSettingValue("newRate"); - bool daily = Mod::get()->template getSettingValue("daily"); - bool weekly = Mod::get()->template getSettingValue("weekly"); - bool event = Mod::get()->template getSettingValue("event"); - bool smallChest = Mod::get()->template getSettingValue("smallChest"); - bool largeChest = Mod::get()->template getSettingValue("largeChest"); - bool list = Mod::get()->template getSettingValue("newListRate"); - bool announcement = Mod::get()->template getSettingValue("announcement"); - eventType = data.type; - if (eventType == EventType::Rate && !newRate) { - EventsPush::eventCompletedCallback(scene); - return true; - } - if (eventType == EventType::Daily && !daily) { - EventsPush::eventCompletedCallback(scene); - return true; - } - if (eventType == EventType::Weekly && !weekly) { - EventsPush::eventCompletedCallback(scene); - return true; - } - if (eventType == EventType::smallChest && !smallChest) { - EventsPush::eventCompletedCallback(scene); - return true; - } - if (eventType == EventType::largeChest && !largeChest) { - EventsPush::eventCompletedCallback(scene); - return true; - } - if (eventType == EventType::List && !list) { - EventsPush::eventCompletedCallback(scene); - return true; - } - if (eventType == EventType::Event && !event) { - EventsPush::eventCompletedCallback(scene); - return true; - } - if (eventType == EventType::Announcement && !announcement) { - EventsPush::eventCompletedCallback(scene); - return true; - } - auto director = CCDirector::sharedDirector(); - auto winSize = director->getWinSize(); - auto bg = cocos2d::extension::CCScale9Sprite::create(data.sprite.c_str(), { .0f, .0f, 80.0f, 80.0f, }); - auto bg_click_spr = cocos2d::extension::CCScale9Sprite::create(data.sprite.c_str(), { .0f, .0f, 80.0f, 80.0f, }); - float lrScale = (float)Mod::get()->template getSettingValue("size"); - auto LrSize = CCSize{ 240, 70 }; // * lrScale for both - bg->setScale(lrScale); - this->setZOrder(zOrder); - zOrder = zOrder + 10; - bg->setContentSize(LrSize); - bg_click_spr->setContentSize(LrSize); - // 0 / 0 = bottom left - // screen width / screen height = top right - // screen width divided by 2 / screen height divided by 2 = middle - - // TODO : click to notifications to be redirected to specific content - auto layer = scene->getChildren()->objectAtIndex(0); - std::string layerName = typeid(*layer).name() + 6; - if (layerName != "PlayLayer" && layerName != "PauseLayer" && layerName != "LevelEditorLayer") { - //auto bg_btn = CCMenuItemSpriteExtra::create(bg_click_spr, this, menu_selector(EventsPush::onClickBtn)); - menu->addChild(bg_click_spr); - } - - menu->setPosition({ bg->getContentSize().width / 2, bg->getContentSize().height / 2 }); - bg->addChild(menu); - this->addChild(bg); - - auto node = CCNode::create(); - - if (eventType != EventType::smallChest && eventType != EventType::largeChest && eventType != EventType::Announcement) { - CCSprite* diffFace; - GJDifficultySprite* mythic = nullptr; - if (!data.demon) { - diffFace = cocos2d::CCSprite::createWithSpriteFrameName(getDifficultyIcon(starsum)); - mythic = GJDifficultySprite::create(static_cast(getDifficulty(starsum)), static_cast(0)); - } else { - diffFace = cocos2d::CCSprite::createWithSpriteFrameName(getDemonDifficultyIcon(starsum)); - mythic = GJDifficultySprite::create(static_cast(getDemonDifficulty(starsum)), static_cast(0)); - } - - diffFace->setPosition({26.f, 43.f}); - diffFace->setScale(.8F); - CCSprite* moon = cocos2d::CCSprite::createWithSpriteFrameName("moon_small01_001.png"); - CCSprite* featured = cocos2d::CCSprite::createWithSpriteFrameName("GJ_featuredCoin_001.png"); - CCSprite* epic = cocos2d::CCSprite::createWithSpriteFrameName("GJ_epicCoin_001.png"); - CCSprite* legendary = cocos2d::CCSprite::createWithSpriteFrameName("GJ_epicCoin2_001.png"); - mythic->updateFeatureState(static_cast(4)); - - std::string starcountstr = std::to_string(stars); - auto starcount = cocos2d::CCLabelBMFont::create(starcountstr.c_str(), "bigFont.fnt"); - starcount->setPosition({25, 18}); - starcount->setAnchorPoint({1, 0.5}); - starcount->setScale(0.35f); - bg->addChild(starcount); - CCSprite* star; - if (eventType == EventType::List) { - star = cocos2d::CCSprite::createWithSpriteFrameName("diamond_small01_001.png"); - } else { - star = cocos2d::CCSprite::createWithSpriteFrameName("star_small01_001.png"); - } - star->setPosition({31, 18}); - star->setScale(.775F); - moon->setPosition({31, 18}); - moon->setScale(.775F); - - if (data.platformer) bg->addChild(moon); - else bg->addChild(star); - - featured->setPosition({26.f, 43.f}); - epic->setPosition({26.f, 43.f}); - legendary->setPosition({26.f, 43.f}); - mythic->setPosition({26.f, 43.f}); - featured->setScale(.8F); - epic->setScale(.8F); - legendary->setScale(.8F); - mythic->setScale(.8F); - - switch (rateType) { - default: // Rate - bg->addChild(diffFace); - break; - case 1: // Featured - bg->addChild(featured); - bg->addChild(diffFace); - break; - case 2: // Epic - bg->addChild(epic); - bg->addChild(diffFace); - break; - case 3: // Legendary - bg->addChild(legendary); - bg->addChild(diffFace); - - if (Mod::get()->template getSettingValue("customDifficultyFaces")) { - CCSprite* legendaryFace = nullptr; - if (!data.demon) { - if (starsum >= 10) { - std::string diffStr = std::to_string(static_cast(getDifficulty(starsum))); - auto name = "difficulty_0" + diffStr + "_legendaryIcon.png"; - legendaryFace = CCSprite::create((""_spr+name).c_str()); - } - } else { - if (starsum < 6) { - std::string diffStr = std::to_string(static_cast(getDemonDifficulty(starsum))); - auto name = "difficulty_0" + diffStr + "_legendaryIcon.png"; - legendaryFace = CCSprite::create((""_spr+name).c_str()); - } else { - std::string diffStr = std::to_string(static_cast(getDemonDifficulty(starsum))); - auto name = "difficulty_" + diffStr + "_legendaryIcon.png"; - legendaryFace = CCSprite::create((""_spr+name).c_str()); - } - } - - if (legendaryFace != nullptr) { - legendaryFace->setPosition({26.f, 48.f}); - legendaryFace->setScale(.8F); - bg->addChild(legendaryFace); - } - } - - break; - case 4: // Mythic - bg->addChild(mythic); - - if (Mod::get()->template getSettingValue("customDifficultyFaces")) { - CCSprite* mythicFace = nullptr; - if (!data.demon) { - if (starsum >= 10) { - std::string diffStr = std::to_string(static_cast(getDifficulty(starsum))); - auto name = "difficulty_0" + diffStr + "_mythicIcon.png"; - mythicFace = CCSprite::create((""_spr+name).c_str()); - } - } else { - if (starsum < 6) { - std::string diffStr = std::to_string(static_cast(getDemonDifficulty(starsum))); - auto name = "difficulty_0" + diffStr + "_mythicIcon.png"; - mythicFace = CCSprite::create((""_spr+name).c_str()); - } else { - std::string diffStr = std::to_string(static_cast(getDemonDifficulty(starsum))); - auto name = "difficulty_" + diffStr + "_mythicIcon.png"; - mythicFace = CCSprite::create((""_spr+name).c_str()); - } - } - - if (mythicFace != nullptr) { - mythicFace->setPosition({26.f, 48.f}); - mythicFace->setScale(.8F); - bg->addChild(mythicFace); - } - } - - break; - } - - auto verifiedCoinSpr1 = cocos2d::CCSprite::createWithSpriteFrameName("GJ_coinsIcon2_001.png"); - verifiedCoinSpr1->setScale(0.35f); - auto verifiedCoinSpr2 = cocos2d::CCSprite::createWithSpriteFrameName("GJ_coinsIcon2_001.png"); - verifiedCoinSpr2->setScale(0.35f); - auto verifiedCoinSpr3 = cocos2d::CCSprite::createWithSpriteFrameName("GJ_coinsIcon2_001.png"); - verifiedCoinSpr3->setScale(0.35f); - - if (areCoinsVerified == 0) { - verifiedCoinSpr1->setColor({255, 175, 75}); - verifiedCoinSpr2->setColor({255, 175, 75}); - verifiedCoinSpr3->setColor({255, 175, 75}); - } - - if (coins == 1 || coins == 3) { - verifiedCoinSpr2->setPosition({ -52, -22 }); - node->addChild(verifiedCoinSpr2); - - if (coins == 3) { - verifiedCoinSpr1->setPosition({ -60, -22 }); - verifiedCoinSpr3->setPosition({ -44, -22 }); - - node->addChild(verifiedCoinSpr1); - node->addChild(verifiedCoinSpr3); - } - } else if (coins == 2) { - verifiedCoinSpr1->setPosition({ -55, -22 }); - verifiedCoinSpr2->setPosition({ -48, -22 }); - - node->addChild(verifiedCoinSpr1); - node->addChild(verifiedCoinSpr2); - } - - // Progress Bar for lists - if (eventType == EventType::List) { - auto barSpriteBack = CCSprite::create("GJ_progressBar_001.png"); - barSpriteBack->setScaleX(0.38f); - barSpriteBack->setScaleY(0.45f); - barSpriteBack->setPosition({ 38, 3 }); - barSpriteBack->setPositionY(3 - 19.f); - barSpriteBack->setPositionX(38); - barSpriteBack->setColor({0, 0, 0}); - barSpriteBack->setOpacity(100); - barSpriteBack->setZOrder(10); - barSpriteBack->setID("progress-bar-list"_spr); - node->addChild(barSpriteBack); - - auto barSpriteTop = CCSprite::create("GJ_progressBar_001.png"); - barSpriteTop->setScaleY(0.4f); - barSpriteTop->setPosition({ 2, 10 }); - barSpriteTop->setAnchorPoint({0, 0.5}); - barSpriteTop->setOpacity(255); - barSpriteTop->setZOrder(11); - - CCPoint rectangle[4] = { - CCPoint(0, 0), - CCPoint(0, 20), - CCPoint(barSpriteBack->getScaledContentSize().width * -2.5f, 20), - CCPoint(barSpriteBack->getScaledContentSize().width * -2.5f, 0) - }; - - auto clippingNode = CCClippingNode::create(); - auto barMask = CCDrawNode::create(); - barMask->drawPolygon(rectangle, 4, ccc4FFromccc3B({0, 0, 0}), 0, ccc4FFromccc3B({0, 0, 0})); - clippingNode->setStencil(barMask); - clippingNode->addChild(barSpriteTop); - clippingNode->setPositionX(330); - barSpriteBack->addChild(clippingNode); - barSpriteTop->setPositionX(-666); - - // Get datas for levels - int maxToCompleteList = data.maxToCompleteList; - std::vector levels = split_str(data.levels_list, ','); - - // Get client data for levels - GameLevelManager* gameLevelManager = GameLevelManager::sharedState(); - CCArray* levelsData = gameLevelManager->getCompletedLevels(false); - - int completedLevels = 0; - int nbLevels = 0; - - while (levels.size() > 0) { - std::string id = levels[0]; - nbLevels++; - - for (int i = 0; i < levelsData->count(); i++) { - auto level = static_cast(levelsData->objectAtIndex(i)); - if (std::to_string(level->m_levelID) == id) { - if (level->m_normalPercent == 100) completedLevels++; - } - } - - levels.erase(levels.begin()); - } - - // min -666 | max -337 - // Calculate position for Progress Bar (between these values based on percentage) - float percentage; - CCLabelBMFont* progressText; - - if (completedLevels >= maxToCompleteList) { - percentage = (float)completedLevels / (float)nbLevels; - progressText = CCLabelBMFont::create((std::to_string(completedLevels) + "/" + std::to_string(nbLevels)).c_str(), "bigFont.fnt"); - barSpriteTop->setColor({ 100, 255, 255 }); - starcount->setColor({ 100, 255, 255 }); - - auto listCompleted = CCSprite::createWithSpriteFrameName("GJ_completesIcon_001.png"); - listCompleted->setPosition({ 94, -15 }); - listCompleted->setScale(0.55f); - listCompleted->setZOrder(13); - node->addChild(listCompleted); - } else { - percentage = (float)completedLevels / (float)maxToCompleteList; - progressText = CCLabelBMFont::create((std::to_string(completedLevels) + "/" + std::to_string(maxToCompleteList)).c_str(), "bigFont.fnt"); - barSpriteTop->setColor({ 255, 84, 50 }); - - auto listUncompleted = CCSprite::createWithSpriteFrameName("diamond_small01_001.png"); - listUncompleted->setPosition({ 94, -15 }); - listUncompleted->setScale(0.55f); - listUncompleted->setZOrder(13); - node->addChild(listUncompleted); - } - - auto moveAction = CCEaseSineOut::create(CCMoveBy::create(0.f, { (percentage * 337), 0 })); - barSpriteTop->runAction(moveAction); - - // Add text for Progress Bar - progressText->setPosition({ 38, -15 }); - progressText->setScale(0.35f); - progressText->setZOrder(13); - node->addChild(progressText); - } - } - - auto title = cocos2d::CCLabelBMFont::create(data.title.c_str(), "goldFont.fnt"); - if (eventType == EventType::smallChest) { - title->setPosition({ -65, 26 }); - } else if (eventType == EventType::largeChest) { - title->setPosition({ -54, 26 }); - } else if (eventType == EventType::List) { - title->setPosition({ -27, 27 }); - } else if (eventType == EventType::Announcement) { - title->setString("Announcement"); - title->setPosition({ -65, 26 }); - auto subtitle = cocos2d::CCLabelBMFont::create(data.title.c_str(), "bigFont.fnt"); - subtitle->limitLabelWidth(200, 0.46f, 0.1f); - subtitle->setAnchorPoint({ 0, 0.5 }); - subtitle->setPosition({ -65, 10 }); - node->addChild(subtitle); - } else { - title->setPosition({ -27, 23 }); - } - title->setScale(.575F); - title->setAnchorPoint({ 0, 0.5 }); - node->addChild(title); - if (eventType != EventType::Announcement) { - auto level_title = cocos2d::CCLabelBMFont::create(data.level_name.c_str(), "bigFont.fnt"); - if (eventType == EventType::List) { - level_title->setPosition({ -27, 11 }); - } else { - level_title->setPosition({ -27, 3 }); - } - level_title->setScale(.46F); - - level_title->setAnchorPoint({ 0, 0.5 }); - - auto level_by = cocos2d::CCLabelBMFont::create(data.level_creator.c_str(), "goldFont.fnt"); - if (eventType == EventType::List) { - level_by->setPosition({ -27, -2 }); - } else { - level_by->setPosition({ -27, -11 }); - } - level_by->setScale(.46F); - level_by->limitLabelWidth(120, 0.46f, 0.1f); - level_by->setAnchorPoint({ 0, 0.5 }); - node->addChild(level_by); - level_title->limitLabelWidth(120, 0.46f, 0.1f); - node->addChild(level_title); - } - - if (eventType == EventType::Daily || eventType == EventType::Weekly || eventType == EventType::Event) { - CCSprite* crown; - if (eventType == EventType::Daily) { - crown = cocos2d::CCSprite::createWithSpriteFrameName("gj_dailyCrown_001.png"); - } else if (eventType == EventType::Event) { - crown = cocos2d::CCSprite::createWithSpriteFrameName("gj_eventCrown_001.png"); - } else { - crown = cocos2d::CCSprite::createWithSpriteFrameName("gj_weeklyCrown_001.png"); - } - crown->setScale(.45F); - crown->setPosition({ 45, 45 }); - node->addChild(crown); - } else if (eventType == EventType::smallChest) { - auto chest = cocos2d::CCSprite::createWithSpriteFrameName("chest_01_02_001.png"); - chest->setScale(.45F); - chest->setPosition({ 45, -3 }); - node->addChild(chest); - } else if (eventType == EventType::largeChest) { - auto chest = cocos2d::CCSprite::createWithSpriteFrameName("chest_02_02_001.png"); - chest->setScale(.4F); - chest->setPosition({ 45, -3 }); - node->addChild(chest); - - } else if (eventType == EventType::List) { - auto list = cocos2d::CCSprite::createWithSpriteFrameName("GJ_listAddBtn_001.png"); - list->setPosition({ 139, -8 }); - node->addChild(list); - } - - node->setAnchorPoint({ 0.5, 0.5 }); - node->setPosition({ 77, 30 }); - - bg->addChild(node); - - this->setTag(1932); - - // Move action - //CCDelayTime - - float delayTime = (float)Mod::get()->template getSettingValue("time"); - - auto cornerId = Mod::get()->getSettingValue("notificationPlacement"); - float moveX = .0F; - switch (cornerId) { - case SettingPosEnum::TopLeft: // top left - bg->setPosition((-(bg->getContentSize().width / 2)) * lrScale, ((winSize.height - (bg->getContentSize().height / 2)) - (20 * lrScale))); - moveX = (bg->getContentSize().width) * lrScale; - break; - case SettingPosEnum::TopRight: // top right - bg->setPosition(winSize.width + ((bg->getContentSize().width / 2) * lrScale), ((winSize.height - (bg->getContentSize().height / 2)) - (20 * lrScale))); - moveX = -(bg->getContentSize().width * lrScale); - break; - case SettingPosEnum::BottomLeft: // bottom left - bg->setPosition((-(bg->getContentSize().width / 2)) * lrScale, (bg->getContentSize().height / 2) * lrScale); - moveX = (bg->getContentSize().width) * lrScale; - break; - case SettingPosEnum::BottomRight: // bottom right - bg->setPosition({ winSize.width + ((bg->getContentSize().width / 2) * lrScale), (bg->getContentSize().height / 2) * lrScale}); - moveX = -((bg->getContentSize().width) * lrScale); - break; - } - - bg->runAction(CCSequence::create( - CCEaseOut::create(CCMoveBy::create(0.5f, { moveX, 0.0f }), 0.6f), - CCDelayTime::create(delayTime), - CCEaseIn::create(CCMoveBy::create(0.5f, { -moveX, 0.0f }), 0.6f), - CCDelayTime::create(0.5F), - CCCallFunc::create(this, callfunc_selector(EventsPush::destroySelf)), - nullptr - )); - - float volume = 0.0f; - if (Mod::get()->template getSettingValue("sfx-link")) { - volume = GameManager::get()->m_sfxVolume; - } else { - volume = Mod::get()->template getSettingValue("sfx-volume"); - } - - if (Mod::get()->template getSettingValue("sfx") && (eventType != EventType::smallChest && eventType != EventType::largeChest)) FMODAudioEngine::sharedEngine()->playEffect("crystal01.ogg", 1, 1, volume); - if (Mod::get()->template getSettingValue("sfx") && (eventType == EventType::smallChest || eventType == EventType::largeChest)) FMODAudioEngine::sharedEngine()->playEffect("reward01.ogg", 1, 1, volume); - return true; -} - -void EventsPush::stopNow(CCScene* scene) { - EventsPush::eventCompletedCallback(scene); -} - -void EventsPush::pushRateLevel(CCScene* self, std::string data) { - EventData eventData = matjson::Serialize::fromJson(matjson::parse(data).unwrapOrDefault()).unwrapOrDefault(); - /*log::info( - "EventData [\ndemon = {};\nstarsum = {};\nstars = {};\nrate = {};\ntype = {};\ntitle = {};\nsprite = {};\nlevel_name = {};\nlevel_creator = {};\ncoins = {};\nverified_coins = {};\nplatformer = {};\nlevel_id = {};\nlevels_list = {};\nmaxToCompleteList = {};\n]", - eventData.demon, - eventData.starsum, - eventData.stars, - eventData.rate, - GDUtils::Events::RateEvent::typeToInt(eventData.type), - eventData.title, - eventData.sprite, - eventData.level_name, - eventData.level_creator, - eventData.coins, - eventData.verified_coins, - eventData.platformer, - eventData.level_id, - eventData.levels_list, - eventData.maxToCompleteList - );*/ - pushRateLevel(self, eventData); -} - -void EventsPush::pushRateLevel(CCScene* self, EventData data) { - // Enqueue the event - eventQueue.push(data); - - // If no event is being processed, start processing events - if (!processingEvents) { - EventsPush::processNextEvent(self); - } -} - -void EventsPush::processNextEvent(CCScene* self) { - if (!eventQueue.empty()) { - auto data = eventQueue.front(); - eventQueue.pop(); - processingEvents = true; - - auto layer = EventsPush::create(data); - GDUtils::Events::OnRate(data).post(); - // Set a callback function that will be called when the event is completed - //layer->setEventCompletedCallback(std::bind(&EventsPush::eventCompletedCallback, this)); - if (layer && self) self->addChild(layer); - } -} - -void EventsPush::eventCompletedCallback(CCScene* self) { - // Event is completed, set processingEvents to false - processingEvents = false; - - // Process the next event (if any) - EventsPush::processNextEvent(self); -} - -$execute { - new EventListener>(+[](GDUtils::Events::RateEvent* e) { - if (auto scene = CCScene::get()) { - EventsPush::pushRateLevel(scene, e->getData()); - } - return ListenerResult::Stop; - }); -} diff --git a/src/Notifications/EventsPush.h b/src/Notifications/EventsPush.h deleted file mode 100644 index 4ac8aec..0000000 --- a/src/Notifications/EventsPush.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include -#include -#include "../../include/RateEvent.hpp" -#include "../includes.h" -using namespace geode::prelude; - -class EventsPush : public CCLayer { - protected: - GJGameLevel* level = GJGameLevel::create(); - #ifdef GEODE_IS_MACOS - int levelId = 0; // because for some reason GJGameLevel doesnt even work :( - #endif - EventType eventType = EventType::NA; - virtual bool init(EventData data); - public: - void destroySelf(); - void onClickBtn(CCObject*); - static EventsPush* create(EventData data); - static void pushRateLevel(CCScene* self, std::string data); - static void pushRateLevel(CCScene* self, EventData data); - static void processNextEvent(CCScene* self); - static void eventCompletedCallback(CCScene* self); - static void stopNow(CCScene* scene); - static GJGameLevel* convertLevelToJSON(std::string& data); - static std::vector getWords(std::string s, std::string delim); -}; diff --git a/src/ProcessLambdas.cpp b/src/ProcessLambdas.cpp deleted file mode 100644 index ae91778..0000000 --- a/src/ProcessLambdas.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "ProcessLambdas.h" -cocos2d::CCLayer* queueLayer = nullptr; -cocos2d::SEL_MenuHandler queueCallback = nullptr; -bool startCallbackQueue = false; -void ProcessLambdas::callMenuHandler(cocos2d::CCLayer* self, cocos2d::SEL_MenuHandler callback) { - startCallbackQueue = true; - queueLayer = self; - queueCallback = callback; -} -void ProcessLambdas::processMenuHandler() { - startCallbackQueue = false; - (queueLayer->*queueCallback)(queueLayer); - queueLayer = nullptr; - queueCallback = nullptr; -} -bool ProcessLambdas::shouldProcessMenuHandler() { - return startCallbackQueue; -} -MenuHandlerResponse ProcessLambdas::getMenuHandler() { - MenuHandlerResponse response; - response.m_queueLayer = queueLayer; - response.m_queueCallback = queueCallback; - return response; -} diff --git a/src/ProcessLambdas.h b/src/ProcessLambdas.h deleted file mode 100644 index 0277689..0000000 --- a/src/ProcessLambdas.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once -#include -// too lazy to deal with pairs or tuples -struct MenuHandlerResponse { - cocos2d::CCLayer* m_queueLayer; - cocos2d::SEL_MenuHandler m_queueCallback; -}; - -// bad coding ik, dont blame me -class ProcessLambdas { - public: - static void callMenuHandler(cocos2d::CCLayer* self, cocos2d::SEL_MenuHandler callback); - static bool shouldProcessMenuHandler(); - static MenuHandlerResponse getMenuHandler(); - static void processMenuHandler(); -}; diff --git a/src/Settings/CustomSettings.cpp b/src/Settings/CustomSettings.cpp deleted file mode 100644 index fcd38f9..0000000 --- a/src/Settings/CustomSettings.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "CustomSettings.hpp" -#include -#include "../includes.h" - -SettingNodeV3* SettingPosValue::createNode(float width) { - return SettingPosNode::create(static_pointer_cast(shared_from_this()), width); -} -SettingNodeV3* SettingCreditsValue::createNode(float width) { - return SettingCreditsNode::create(static_pointer_cast(shared_from_this()), width); -} diff --git a/src/Settings/CustomSettings.hpp b/src/Settings/CustomSettings.hpp deleted file mode 100644 index 9bb73d9..0000000 --- a/src/Settings/CustomSettings.hpp +++ /dev/null @@ -1,272 +0,0 @@ -#pragma once -#include "CreditsBetaMenu.h" -#include "CreditsMenu.h" -#include -using namespace geode::prelude; - - - - -/* - Notification Position -*/ - -const int DEFAULT_POS = 4; - -enum class SettingPosEnum : int { - TopLeft, - TopRight, - BottomLeft, - BottomRight -}; - -template <> -struct matjson::Serialize { - static matjson::Value toJson(SettingPosEnum const& value) { - switch (value) { - case SettingPosEnum::TopLeft: - return 1; - case SettingPosEnum::TopRight: - return 2; - case SettingPosEnum::BottomLeft: - return 3; - default: - case SettingPosEnum::BottomRight: - return 4; - } - } - static Result fromJson(matjson::Value const& value) { - switch (value.asInt().unwrapOrDefault()) { - case 1: return Ok(SettingPosEnum::TopLeft); - case 2: return Ok(SettingPosEnum::TopRight); - case 3: return Ok(SettingPosEnum::BottomLeft); - case 4: return Ok(SettingPosEnum::BottomRight); - default: return Err("Invalid SettingPosEnum value '{}'", value.asInt().unwrapOrDefault()); - } - } - static bool is_json(matjson::Value const& json) { - return json.isNumber() || json.isString(); - } -}; - -class SettingPosValue : public SettingBaseValueV3 { -public: - static Result> parse(std::string const& key, std::string const& modID, matjson::Value const& json) { - auto res = std::make_shared(); - auto root = checkJson(json, "SettingPosValue"); - res->parseBaseProperties(key, modID, root); - root.checkUnknownKeys(); - return root.ok(std::static_pointer_cast(res)); - } - SettingNodeV3* createNode(float width) override; -}; - - -template <> -struct geode::SettingTypeForValueType { - using SettingType = SettingPosValue; -}; - -class SettingPosNode : public SettingValueNodeV3 { -protected: - CCMenuItemToggler* tlBtn; - CCMenuItemToggler* trBtn; - CCMenuItemToggler* blBtn; - CCMenuItemToggler* brBtn; - - int getActiveCornerTag(SettingPosEnum corner) { - switch (corner) { - case SettingPosEnum::TopLeft: // Top Left - return 2004; - case SettingPosEnum::TopRight: // Top Right - return 2005; - case SettingPosEnum::BottomLeft: // Bottom Left - return 2006; - case SettingPosEnum::BottomRight: // Bottom Right - default: - return 2007; - } - } - SettingPosEnum tagToCorner(int tag) { - switch (tag) { - case 2004: // Top Left - return SettingPosEnum::TopLeft; - case 2005: // Top Right - return SettingPosEnum::TopRight; - case 2006: // Bottom Left - return SettingPosEnum::BottomLeft; - default: - case 2007: // Bottom Right - return SettingPosEnum::BottomRight; - } - } - - bool init(std::shared_ptr setting, float width) { - if (!SettingValueNodeV3::init(setting, width)) - return false; - this->setContentSize({ width, 70.f }); - CCSprite* toggleOn = CCSprite::createWithSpriteFrameName("GJ_checkOn_001.png"); - CCSprite* toggleOff = CCSprite::createWithSpriteFrameName("GJ_checkOff_001.png"); - toggleOn->setScale(.7F); - toggleOff->setScale(.7F); - tlBtn = CCMenuItemToggler::create( - toggleOn, - toggleOff, - this, - menu_selector(SettingPosNode::onCornerClick) - ); - trBtn = CCMenuItemToggler::create( - toggleOn, - toggleOff, - this, - menu_selector(SettingPosNode::onCornerClick) - ); - blBtn = CCMenuItemToggler::create( - toggleOn, - toggleOff, - this, - menu_selector(SettingPosNode::onCornerClick) - ); - brBtn = CCMenuItemToggler::create( - toggleOn, - toggleOff, - this, - menu_selector(SettingPosNode::onCornerClick) - ); - tlBtn->setTag(getActiveCornerTag(SettingPosEnum::TopLeft)); - trBtn->setTag(getActiveCornerTag(SettingPosEnum::TopRight)); - blBtn->setTag(getActiveCornerTag(SettingPosEnum::BottomLeft)); - brBtn->setTag(getActiveCornerTag(SettingPosEnum::BottomRight)); - getButtonMenu()->setContentSize({width / 2, 45.F}); - getButtonMenu()->addChildAtPosition(tlBtn, Anchor::TopLeft); - getButtonMenu()->addChildAtPosition(trBtn, Anchor::TopRight); - getButtonMenu()->addChildAtPosition(blBtn, Anchor::BottomLeft); - getButtonMenu()->addChildAtPosition(brBtn, Anchor::BottomRight); - getButtonMenu()->updateLayout(); - getButtonMenu()->setAnchorPoint({0.5, 0.5}); - getButtonMenu()->updateAnchoredPosition(Anchor::Center, {0, 0}); - this->getNameLabel()->setVisible(false); - auto currentCorner = static_cast(this->getValue()); - tlBtn->toggle(!(tlBtn->getTag() == getActiveCornerTag(currentCorner))); - trBtn->toggle(!(trBtn->getTag() == getActiveCornerTag(currentCorner))); - blBtn->toggle(!(blBtn->getTag() == getActiveCornerTag(currentCorner))); - brBtn->toggle(!(brBtn->getTag() == getActiveCornerTag(currentCorner))); - this->updateState(nullptr); - return true; - } - - void updateState(CCNode* invoker) override { - SettingValueNodeV3::updateState(invoker); - auto currentCorner = static_cast(this->getValue()); - } - void onCornerClick(CCObject* sender) { - tlBtn->toggle(true); - trBtn->toggle(true); - blBtn->toggle(true); - brBtn->toggle(true); - SettingPosEnum value = tagToCorner(sender->getTag()); - this->setValue(value, static_cast(sender)); - }; - void onResetToDefault() override { - tlBtn->toggle(true); - trBtn->toggle(true); - blBtn->toggle(true); - brBtn->toggle(false); - this->setValue(SettingPosEnum::BottomRight, nullptr); - } -public: - static SettingPosNode* create(std::shared_ptr setting, float width) { - auto ret = new SettingPosNode(); - if (ret && ret->init(setting, width)) { - ret->autorelease(); - return ret; - } - CC_SAFE_DELETE(ret); - return nullptr; - } -}; - -/* - Credits -*/ - -class SettingCreditsValue : public SettingV3 { -public: - static Result> parse(std::string const& key, std::string const& modID, matjson::Value const& json) { - auto res = std::make_shared(); - auto root = checkJson(json, "SettingCreditsValue"); - res->init(key, modID, root); - res->parseNameAndDescription(root); - res->parseEnableIf(root); - root.checkUnknownKeys(); - return root.ok(std::static_pointer_cast(res)); - } - - bool load(matjson::Value const& json) override { - return true; - } - bool save(matjson::Value& json) const override { - return true; - } - bool isDefaultValue() const override { - return true; - } - void reset() override {} - SettingNodeV3* createNode(float width) override; -}; - - -class SettingCreditsNode : public SettingNodeV3 { -protected: - bool init(std::shared_ptr setting, float width) { - if (!SettingNodeV3::init(setting, width)) - return false; - this->setContentSize({ width, 40.f }); - auto creditsSpr = ButtonSprite::create("Credits", "bigFont.fnt", "GJ_button_01.png"); - creditsSpr->setScale(.6F); - auto creditsBtn = CCMenuItemSpriteExtra::create( - creditsSpr, - this, - menu_selector(SettingCreditsNode::onCreditsBtn) - ); - auto betaTestersSpr = ButtonSprite::create("Beta Testers", "bigFont.fnt", "GJ_button_01.png"); - betaTestersSpr->setScale(.6F); - auto betaTestersBtn = CCMenuItemSpriteExtra::create( - betaTestersSpr, - this, - menu_selector(SettingCreditsNode::onBetaBtn) - ); - getButtonMenu()->setContentWidth(width); - getButtonMenu()->addChildAtPosition(creditsBtn, Anchor::Center, {-55, 0}); - getButtonMenu()->addChildAtPosition(betaTestersBtn, Anchor::Center, {85, 0}); - getButtonMenu()->updateLayout(); - getNameLabel()->setVisible(false); - return true; - } - void onCommit() override {} - void onResetToDefault() override {} - -public: - void onCreditsBtn(CCObject*) { - CreditsMenu::create()->show(); - } - void onBetaBtn(CCObject*) { - CreditsBetaMenu::create()->show(); - } - - bool hasUncommittedChanges() const override { - return false; - } - bool hasNonDefaultValue() const override { - return false; - } - static SettingCreditsNode* create(std::shared_ptr setting, float width) { - auto ret = new SettingCreditsNode(); - if (ret && ret->init(setting, width)) { - ret->autorelease(); - return ret; - } - CC_SAFE_DELETE(ret); - return nullptr; - } -}; diff --git a/src/Settings/TestButton.cpp b/src/Settings/TestButton.cpp deleted file mode 100644 index 571104a..0000000 --- a/src/Settings/TestButton.cpp +++ /dev/null @@ -1,175 +0,0 @@ -#include -#include "../Notifications/EventsPush.h" - -using namespace geode::prelude; - -/* - --- Test --- -*/ - -int cycleTypes = -1; - -class SettingTestValue : public SettingV3 { -public: - static Result> parse(std::string const& key, std::string const& modID, matjson::Value const& json) { - auto res = std::make_shared(); - auto root = checkJson(json, "SettingTestValue"); - res->init(key, modID, root); - res->parseNameAndDescription(root); - res->parseEnableIf(root); - root.checkUnknownKeys(); - return root.ok(std::static_pointer_cast(res)); - } - - bool load(matjson::Value const& json) override { - return true; - } - bool save(matjson::Value& json) const override { - return true; - } - bool isDefaultValue() const override { - return true; - } - void reset() override {} - SettingNodeV3* createNode(float width) override; -}; - -class SettingTestNode : public SettingNodeV3 { -protected: - bool init(std::shared_ptr setting, float width) { - if (!SettingNodeV3::init(setting, width)) - return false; - this->setContentSize({ width, 35.f }); - auto label = CCLabelBMFont::create("Test", "bigFont.fnt"); - - label->setScale(.6F); - - auto playSpr = CCSprite::createWithSpriteFrameName("GJ_playBtn2_001.png"); - - playSpr->setScale(.4F); - - auto testBtn = CCMenuItemSpriteExtra::create( - playSpr, - this, - menu_selector(SettingTestNode::onTestBtn) - ); - - getButtonMenu()->setContentWidth(width); - getButtonMenu()->addChildAtPosition(label, Anchor::Left, {42, 0}); - getButtonMenu()->addChildAtPosition(testBtn, Anchor::Right, {-15, 0}); - getButtonMenu()->updateLayout(); - - getNameLabel()->setVisible(false); - - return true; - } - void onCommit() override {} - void onResetToDefault() override {} - -public: - void onTestBtn(CCObject*) { - auto scene = CCDirector::sharedDirector()->getRunningScene(); - cycleTypes = cycleTypes + 1; - if (cycleTypes > 4) cycleTypes = 0; - bool newRate = Mod::get()->getSettingValue("newRate"); - bool daily = Mod::get()->getSettingValue("daily"); - bool weekly = Mod::get()->getSettingValue("weekly"); - if (!newRate && cycleTypes == 0) cycleTypes = 1; - if (!daily && cycleTypes == 1) cycleTypes = 2; - if (!weekly && cycleTypes == 2) cycleTypes = 3; - if (!newRate && !daily && !weekly) { - cycleTypes = 5; - } - - EventData data; - data.type = EventType::Rate; - data.rate = 1; - data.coins = 3; - data.verified_coins = true; - data.level_creator = "by RobTop"; - //{'demon': 1, 'type': 1, 'starsum': 6, 'stars': 10, 'rate': 1, 'title': 'BRAINPOWER Let the base kick!', 'level_name': 'O-oooooooooo AAAAE-A-A-I-A-U-', 'level_creator': ' JO-oooooooooooo AAE-O-A-A-U-U-A- E-eee-ee-eee AAAAE-A-E-I-E-A- JO-ooo-oo-oo-oo EEEEO-A-AAA-AAAA', 'sprite': 'GJ_square01.png'} - switch (cycleTypes) { - case 0: // new rate - data.title = "New Rated Level !"; - data.stars = 1; - data.starsum = 10; - data.level_name = "Stereo Madness"; - break; - case 1: // daily - data.title = "New Daily Level !"; - data.type = EventType::Daily; - data.stars = 9; - data.starsum = 40; - data.level_name = "Cycles"; - break; - case 2: // weekly - data.title = "New Weekly Level !"; - data.demon = true; - data.type = EventType::Weekly; - data.stars = 14; - data.starsum = 7; - data.level_name = "Theory of Everything 2"; - data.sprite = "GJ_square05.png"; - break; - case 3: // Legendary rating test - data.title = "New Rated Level !"; - data.stars = 3; - data.starsum = 20; - data.level_name = "Oh no it's happening"; - data.level_creator = "by ..."; - data.rate = 3; - break; - case 4: // Mythic rating test - data.title = "New Rated Level !"; - data.stars = 100; - data.starsum = 20; - data.type = EventType::Event; - data.level_name = "FIRE IN THE HOLE!"; - data.level_creator = "by GD Community"; - data.rate = 4; - break; - case 5: // in case the user disables everything - data.title = "New Rated Level !"; - data.demon = true; - data.stars = 2; - data.starsum = 6; - data.level_name = "Back On Track"; - data.rate = 1; - break; - default: // not possible - data.title = "hi there hxd user, ghidra user or ida user. (or hi RobTop) Here's a little easter egg for you :)"; - data.demon = true; - data.stars = 14; - data.starsum = 7; - data.sprite = "This will crash! :D"; - break; - } - EventsPush::pushRateLevel(scene, data); - } - bool hasUncommittedChanges() const override { - return false; - } - bool hasNonDefaultValue() const override { - return false; - } - static SettingTestNode* create(std::shared_ptr setting, float width) { - auto ret = new SettingTestNode(); - if (ret && ret->init(setting, width)) { - ret->autorelease(); - return ret; - } - CC_SAFE_DELETE(ret); - return nullptr; - } - std::shared_ptr getSetting() const { - return std::static_pointer_cast(SettingNodeV3::getSetting()); - } -}; - -SettingNodeV3* SettingTestValue::createNode(float width) { - return SettingTestNode::create(static_pointer_cast(shared_from_this()), width); -} - -$execute { - (void)Mod::get()->registerCustomSettingType("test-notification", &SettingTestValue::parse); -} diff --git a/src/Styles/EventLevelInformation.cpp b/src/Styles/EventLevelInformation.cpp deleted file mode 100644 index 630a440..0000000 --- a/src/Styles/EventLevelInformation.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include "EventLevelInformation.h" -#include "Geode/Enums.hpp" -#include - -class $modify(EventPage, DailyLevelPage) { - void onInfo(CCObject* pSender) { - EventLevelInformation::scene(); - } - - bool init(GJTimedLevelType type) { - if (!DailyLevelPage::init(type)) return false; - - if (type != GJTimedLevelType::Event) return true; - - if (!Mod::get()->template getSettingValue("eventLevelInfo")) return true; - - auto infoSpr = CCSprite::createWithSpriteFrameName("info_btn.png"_spr); - auto infoBtn = CCMenuItemSpriteExtra::create(infoSpr, this, menu_selector(EventPage::onInfo)); - - // Put on the corner top left of the background - auto menu = as(this->m_mainLayer->getChildByIDRecursive("main-menu")); - if (menu) { - infoBtn->setPosition({ 14, -194 }); - menu->addChild(infoBtn); - } - - return true; - } -}; - -void EventLevelInformation::scene() { - auto popup = new EventLevelInformation(); - - if (popup && popup->initAnchored(400.0f, 225.0f, "GJ_square02.png")) { - popup->autorelease(); - CCDirector::sharedDirector()->getRunningScene()->addChild(popup, 1000); - } else { - CC_SAFE_DELETE(popup); - } -}; - -bool EventLevelInformation::setup() { - auto winSize = cocos2d::CCDirector::sharedDirector()->getWinSize(); - auto director = cocos2d::CCDirector::sharedDirector(); - - registerWithTouchDispatcher(); - setTouchEnabled(true); - setKeypadEnabled(true); - - EventLevelInformation::loadPage(); - return true; -} - -void EventLevelInformation::loadPage() { - // Make loading circle - loading_circle = LoadingCircle::create(); - loading_circle->setZOrder(25); - loading_circle->setParentLayer(this); - loading_circle->show(); - - // Load the image - std::string URL = "https://clarifygdps.com/gdutils/event_info/image_banner.png?randome=" + std::to_string(static_cast(time(nullptr))); - - auto req = web::WebRequest(); - m_downloadListener.bind([this](web::WebTask::Event* e){ - if (auto res = e->getValue()){ - if (!res->ok()) { - onDownloadFail(); - } else { - auto data = res->data(); - std::thread imageThread = std::thread([data,this](){ - m_image = new CCImage(); - m_image->initWithImageData(const_cast(data.data()),data.size()); - geode::Loader::get()->queueInMainThread([this](){ - imageCreationFinished(m_image); - m_image->release(); - }); - }); - imageThread.detach(); - } - } - }); - - auto downloadTask = req.header("Cache-Control", "no-cache").header("Pragma", "no-cache").get(URL); - m_downloadListener.setFilter(downloadTask); -} - -void EventLevelInformation::imageCreationFinished(CCImage* image) { - fadeLoadingCircle(); - - auto size = this->m_mainLayer->getContentSize(); - auto texture = new CCTexture2D(); - texture->initWithImage(image); - auto spr = CCSprite::createWithTexture(texture); - texture->autorelease(); - spr->setPosition({ size.width / 2, size.height / 2 }); - spr->setScale(1.1f); - - this->m_mainLayer->addChild(spr); -} - -void EventLevelInformation::onDownloadFail() { - fadeLoadingCircle(); - - auto size = this->m_mainLayer->getContentSize(); - auto failLabel = CCLabelBMFont::create("No event banner found.", "bigFont.fnt", 0.0f, kCCTextAlignmentCenter); - failLabel->setPosition({ size.width / 2, size.height / 2 }); - failLabel->setScale(0.7f); - - this->m_mainLayer->addChild(failLabel); -} - -void EventLevelInformation::fadeLoadingCircle() { - if (loading_circle == nullptr) return; - loading_circle->fadeAndRemove(); -}; diff --git a/src/Styles/EventLevelInformation.h b/src/Styles/EventLevelInformation.h deleted file mode 100644 index 9fb406d..0000000 --- a/src/Styles/EventLevelInformation.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include "../includes.h" -#include "Geode/binding/FLAlertLayer.hpp" -#include "../OldBorder.hpp" - -#include - -class EventLevelInformation : public Popup<> { - protected: - EventListener m_downloadListener; - Ref m_image; - LoadingCircle* loading_circle = nullptr; - - bool setup() override; - void loadPage(); - void imageCreationFinished(CCImage* image); - void onDownloadFail(); - void fadeLoadingCircle(); - - public: - static void scene(); -}; \ No newline at end of file diff --git a/src/Styles/GauntletStyle.cpp b/src/Styles/GauntletStyle.cpp deleted file mode 100644 index 76ce68e..0000000 --- a/src/Styles/GauntletStyle.cpp +++ /dev/null @@ -1,1124 +0,0 @@ -#include "../includes.h" -#include -#include -#include "../Utils/ParticleManager.hpp" -#include "Geode/cocos/particle_nodes/CCParticleSystemQuad.h" - -class $modify(CustomGauntletSelectLayer, GauntletSelectLayer) { - void reverseGauntlet(GauntletNode* node) { - CCNode* gauntlet_node = node->m_gauntletInfoNode; - - CCNode* checkmark = node->getChildByID("checkmark-sprite"); - if (checkmark) { - checkmark->setPositionY(78); - - CCNode* checkmark_shadow = node->getChildByID("checkmark-shadow-sprite"); - checkmark_shadow->setPositionY(78); - } - - CCNode* label_reward = gauntlet_node->getChildByID("reward-label"); - if (label_reward) { - label_reward->setPositionY(50); - CCNode* label_reward_shadow = gauntlet_node->getChildByID("reward-shadow-label"); - label_reward_shadow->setPositionY(50); - - CCSprite* chest = static_cast(gauntlet_node->getChildByID("chest-sprite")); - chest->setPositionY(80); - chest->setFlipY(true); - CCSprite* chest_shadow = static_cast(gauntlet_node->getChildByID("chest-shadow-sprite")); - chest_shadow->setPositionY(80); - chest_shadow->setFlipY(true); - } - - CCNode* label_progress = gauntlet_node->getChildByID("gauntlet-progress-label"); - label_progress->setPositionY(29); - - CCNode* label_progress_shadow = gauntlet_node->getChildByID("gauntlet-progress-shadow-label"); - label_progress_shadow->setPositionY(29); - } - - bool init(int p0) { - if (!GauntletSelectLayer::init(p0)) return false; - - if (!Mod::get()->template getSettingValue("gauntletDesign")) return true; - - CCSprite* infoSpr = CCSprite::createWithSpriteFrameName("GJ_infoIcon_001.png"); - CCMenuItemSpriteExtra* infoBtn = CCMenuItemSpriteExtra::create( - infoSpr, - this, - menu_selector(CustomGauntletSelectLayer::onInfoBtn) - ); - - CCSprite* bottom_corner_right = static_cast(this->getChildByIDRecursive("bottom-right-corner")); - if (bottom_corner_right) { - infoBtn->setPosition(bottom_corner_right->getPosition()); - infoBtn->setScale(.8f); - infoBtn->setZOrder(10); - infoBtn->setColor(cocos2d::ccc3(236, 149, 19)); - infoBtn->setID("particle-info-button"_spr); - - CCMenu* menu_btr = static_cast(this->getChildByIDRecursive("bottom-right-menu")); - menu_btr->addChild(infoBtn); - menu_btr->updateLayout(); - - CCParticleSystemQuad* particle_info = GameToolbox::particleFromString("26a-1a1.66a0.3a30a90a180a14a0a1a1a0a7a0a0a0a0a2a1a0a0a1a0a0.568627a0a0.12549a0a1a0a1a1a0a0a1a0a0.501961a0a0a0a1a0a0a0a0.46a0a0a0a0a0a0a0a0a2a1a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - infoBtn->addChild(particle_info); - particle_info->setPosition(infoSpr->getPosition()); - particle_info->setZOrder(9); - } - - return true; - } - - void onInfoBtn(CCObject* pSender) { - FLAlertLayer::create( - nullptr, - "Gauntlets redesign", - R"text( - All new designs for Gauntlets are made by xvia and brift. - Particles are made by GammaReXx. - - Thanks for their contributions! - )text", - "OK", - nullptr, - 300.0f - )->show(); - } - - void setupGauntlets() { - GauntletSelectLayer::setupGauntlets(); - - if (!Mod::get()->template getSettingValue("gauntletDesign")) return; - if (!m_scrollLayer) return; - - for (int i = 0; i < m_scrollLayer->m_pages->count(); i++) { - auto page = static_cast(static_cast(m_scrollLayer->m_pages->objectAtIndex(i))->getChildren()->objectAtIndex(0))->getChildren(); - - for (int j = 0; j < page->count(); j++) { - CCNode* item = static_cast(page->objectAtIndex(j)); - - // Handle spaces - if (j == 0 && page->count() > 1) { - item->setPositionX(item->getPositionX() - 25.0f); - } else if (j == 1 && page->count() == 2) { - item->setPositionX(item->getPositionX() + 25.0f); - } else if (j == 2) { - item->setPositionX(item->getPositionX() + 25.0f); - } - - GauntletNode* node = static_cast(item->getChildByIDRecursive("gauntlet-node")); - - CCLabelBMFont* label = static_cast(node->getChildByID("gauntlet-name-label")); - CCNode* label_shadow = node->getChildByID("gauntlet-name-shadow-label"); - CCNode* label_gauntlet = node->getChildByID("gauntlet-label"); - CCNode* label_shadow_gauntlet = node->getChildByID("gauntlet-shadow-label"); - CCNode* bg = node->getChildByID("background"); - - CCNode* gauntlet_node = node->m_gauntletInfoNode; - CCSprite* gauntlet = static_cast(gauntlet_node->getChildByID("gauntlet-sprite")); - CCNode* gauntlet_shadow = gauntlet_node->getChildByID("gauntlet-shadow-sprite"); - - bg->setVisible(false); - label->setVisible(false); - label_shadow->setVisible(false); - label_gauntlet->setVisible(false); - label_shadow_gauntlet->setVisible(false); - gauntlet->setVisible(false); - gauntlet_shadow->setVisible(false); - - std::string gauntletName = label->getString(); - - auto scaleFactor = 4/CCDirector::get()->getContentScaleFactor(); - - if (gauntletName == "World") { - CCSprite* sprite = CCSprite::create("world_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({1, 16}); - gauntlet->setScale(1); - gauntlet_node->setZOrder(3); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.729412a0a0.352941a0a0.796078a0a1a0a7a0a0a0a0.729412a0a0.352941a0a0.796078a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({10, 24}); - particle->setZOrder(1); - particle->setScaleX(1.310f); - particle->setScaleY(2.610f); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.34902a0a0.466667a0a0.792157a0a1a0a7a0a0a0a0.34902a0a0.466667a0a0.792157a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition({6, 24}); - particle2->setZOrder(1); - particle2->setScaleX(1.310f); - particle2->setScaleY(2.610f); - particle2->setID("gauntlet-particles-2"_spr); - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.360784a0a0.854902a0a0.368627a0a1a0a7a0a0a0a0.360784a0a0.854902a0a0.368627a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setPosition({2, 24}); - particle3->setZOrder(1); - particle3->setScaleX(1.310f); - particle3->setScaleY(2.610f); - particle3->setID("gauntlet-particles-3"_spr); - CCParticleSystemQuad* particle4 = GameToolbox::particleFromString("22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.866667a0a0.839216a0a0.247059a0a1a0a7a0a0a0a0.866667a0a0.839216a0a0.247059a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle4); - particle4->setPosition({-2, 24}); - particle4->setZOrder(1); - particle4->setScaleX(1.310f); - particle4->setScaleY(2.610f); - particle4->setID("gauntlet-particles-4"_spr); - CCParticleSystemQuad* particle5 = GameToolbox::particleFromString("22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.866667a0a0.294118a0a0.247059a0a1a0a7a0a0a0a0.866667a0a0.294118a0a0.247059a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle5); - particle5->setPosition({-6, 24}); - particle5->setZOrder(1); - particle5->setScaleX(1.310f); - particle5->setScaleY(2.610f); - particle5->setID("gauntlet-particles-5"_spr); - CCParticleSystemQuad* particle6 = GameToolbox::particleFromString("22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.729412a0a0.352941a0a0.796078a0a1a0a7a0a0a0a0.729412a0a0.352941a0a0.796078a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle6); - particle6->setPosition({-9, 24}); - particle6->setZOrder(1); - particle6->setScaleX(-1.310f); - particle6->setScaleY(2.610f); - particle6->setID("gauntlet-particles-6"_spr); - CCParticleSystemQuad* particle7 = GameToolbox::particleFromString("22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.34902a0a0.466667a0a0.792157a0a1a0a7a0a0a0a0.34902a0a0.466667a0a0.792157a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle7); - particle7->setPosition({-5, 24}); - particle7->setZOrder(1); - particle7->setScaleX(-1.310f); - particle7->setScaleY(2.610f); - particle7->setID("gauntlet-particles-7"_spr); - CCParticleSystemQuad* particle8 = GameToolbox::particleFromString("22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.360784a0a0.854902a0a0.368627a0a1a0a7a0a0a0a0.360784a0a0.854902a0a0.368627a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle8); - particle8->setPosition({-1, 24}); - particle8->setZOrder(1); - particle8->setScaleX(-1.310f); - particle8->setScaleY(2.610f); - particle8->setID("gauntlet-particles-8"_spr); - CCParticleSystemQuad* particle9 = GameToolbox::particleFromString("22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.866667a0a0.839216a0a0.247059a0a1a0a7a0a0a0a0.866667a0a0.839216a0a0.247059a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle9); - particle9->setPosition({3, 24}); - particle9->setZOrder(1); - particle9->setScaleX(-1.310f); - particle9->setScaleY(2.610f); - particle9->setID("gauntlet-particles-9"_spr); - CCParticleSystemQuad* particle10 = GameToolbox::particleFromString("22a-1a3a0a20a90a0a29a0a0a0a0a0a0a0a0a0a7a0a0a0a0.866667a0a0.294118a0a0.247059a0a1a0a7a0a0a0a0.866667a0a0.294118a0a0.247059a0a1a0a0.4a0a0.4a0a35a0a35a0a-50a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle10); - particle10->setPosition({7, 24}); - particle10->setZOrder(1); - particle10->setScaleX(-1.310f); - particle10->setScaleY(2.610f); - particle10->setID("gauntlet-particles-10"_spr); - CCParticleSystemQuad* particle11 = GameToolbox::particleFromString("38a-1a1.5a0.3a21a90a90a0a0a31a69a0a0a0a0a0a0a2a1a65a57a1a0a1a0a1a0a1a0a5a1a0a0a1a0a1a0a1a0a1a0a0.2a0a0.4a0a0a0a0a0a0a0a0a2a1a0a0a0a169a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle11); - particle11->setPosition({1, 6}); - particle11->setZOrder(1); - particle11->setScaleX(1.710f); - particle11->setScaleY(1.660f); - particle11->setID("gauntlet-particles-11"_spr); - CCParticleSystemQuad* particle12 = GameToolbox::particleFromString("11a-1a1.5a0.3a6a90a90a0a0a31a69a0a0a0a0a0a0a4a1a0a0a1a0a1a0a1a0a1a0a7a1a52a55a1a0a1a0a1a0a1a0a0.2a0a0.4a0a0a0a0a0a0a0a0a2a1a0a0a0a167a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle12); - particle12->setPosition({1, 16}); - particle12->setZOrder(1); - particle12->setScaleX(1.835f); - particle12->setScaleY(1.485f); - particle12->setID("gauntlet-particles-12"_spr); - } else if (gauntletName == "Fantasy") { - CCSprite* sprite = CCSprite::create("fantasy_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.225f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({-2, 14}); - gauntlet->setScale(0.925f); - gauntlet_node->setZOrder(2); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("26a-1a5a0.3a4a-90a14a9a0a17a0a0a0a0a0a0a0a2a1a76a325a0.537255a0a0.898039a0a0.164706a0a1a0a2a1a148a149a0.537255a0a0.898039a0a0.164706a0a1a0a0a0a0.3a0a0a0a0a0a0a0a0a2a0a0a0a0a146a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({gauntlet->getPositionX(), 103}); - particle->setZOrder(1); - particle->setScaleX(2.880f); - particle->setScaleY(4.603f); - particle->setID("gauntlet-particles-1"_spr); - } else if (gauntletName == "Portal") { - CCSprite* sprite = CCSprite::create("portal_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.225f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({-2, 14}); - gauntlet->setScale(0.925f); - gauntlet_node->setZOrder(2); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("13a-1a1a0.3a10a90a90a29a0a11a0a0a0a0a0a0a0a50a1a0a37a0.376471a0a0.109804a0a0.243137a0a1a0a32a1a142a96a0.376471a0a0.109804a0a0.243137a0a1a0a0.5a0a0.3a0a0a0a0a0a0a0a1a2a1a0a0a0a190a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({gauntlet->getPositionX(), 14}); - particle->setZOrder(1); - particle->setScaleX(2.880f); - particle->setScaleY(3.978f); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("13a-1a1a0.3a10a90a90a29a0a11a0a0a0a0a0a0a0a50a1a0a37a0.0705882a0a0.172549a0a0.203922a0a1a0a32a1a142a96a0.0705882a0a0.172549a0a0.203922a0a1a0a0.5a0a0.3a0a0a0a0a0a0a0a1a2a1a0a0a0a190a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition({gauntlet->getPositionX(), 14}); - particle2->setZOrder(1); - particle2->setScaleX(2.880f); - particle2->setScaleY(3.978f); - particle2->setID("gauntlet-particles-2"_spr); - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("38a-1a2a0.3a16a90a180a29a0a11a0a0a0a0a0a0a0a6a1a0a0a0.760784a0a0.380392a0a0.835294a0a1a0a3a1a0a0a0.760784a0a0.380392a0a0.835294a0a1a0a0.18a0a0.49a0a43a0a33a0a-34a0a1a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setPosition({gauntlet->getPositionX(), 14}); - particle3->setZOrder(1); - particle3->setScaleX(1.030f); - particle3->setScaleY(1.030f); - particle3->setID("gauntlet-particles-3"_spr); - CCParticleSystemQuad* particle4 = GameToolbox::particleFromString("38a-1a2a0.3a16a90a180a29a0a11a0a0a0a0a0a0a0a6a1a0a0a0.376471a0a0.690196a0a0.831373a0a1a0a3a1a0a0a0.376471a0a0.690196a0a0.831373a0a1a0a0.18a0a0.49a0a43a0a33a0a-34a0a1a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle4); - particle4->setPosition({gauntlet->getPositionX(), 14}); - particle4->setZOrder(1); - particle4->setScaleX(1.155f); - particle4->setScaleY(1.355f); - particle4->setID("gauntlet-particles-4"_spr); - CCParticleSystemQuad* particle5 = GameToolbox::particleFromString("30a-1a1a0.3a30a90a180a29a0a11a0a0a0a0a0a0a0a4a1a0a0a0.760784a0a0.380392a0a0.835294a0a1a0a2a1a0a0a0.760784a0a0.380392a0a0.835294a0a1a0a0.18a0a0.49a0a43a0a33a0a-41a0a1a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle5); - particle5->setPosition({gauntlet->getPositionX(), 14}); - particle5->setZOrder(1); - particle5->setScaleX(1.455f); - particle5->setScaleY(1.655f); - particle5->setID("gauntlet-particles-5"_spr); - CCParticleSystemQuad* particle6 = GameToolbox::particleFromString("30a-1a1a0.3a30a90a180a29a0a11a0a0a0a0a0a0a0a4a1a0a0a0.376471a0a0.690196a0a0.831373a0a1a0a2a1a0a0a0.376471a0a0.690196a0a0.831373a0a1a0a0.18a0a0.49a0a43a0a33a0a-41a0a1a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle6); - particle6->setPosition({gauntlet->getPositionX(), 14}); - particle6->setZOrder(1); - particle6->setScaleX(1.355f); - particle6->setScaleY(1.855f); - particle6->setID("gauntlet-particles-6"_spr); - } else if (gauntletName == "Demon") { - CCSprite* sprite = CCSprite::create("demon_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.275f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({-1, 22}); - gauntlet->setScale(1.1f); - gauntlet_node->setZOrder(2); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("66a-1a3a0.3a20a90a27a11a0a37a38a0a0a0a0a0a0a5a1a0a0a0.694118a0a0.45098a0a0.054902a0a1a0a2a1a0a0a0.509804a0a0.172549a0a0a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition(gauntlet->getPosition()); - particle->setZOrder(1); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("29a-1a3a0.3a8a90a27a11a0a37a38a0a0a0a0a0a0a50a1a0a0a0.0509804a0a0.0392157a0a0.0352941a0a1a0a50a1a0a0a0.0509804a0a0.0392157a0a0.0352941a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition(gauntlet->getPosition()); - particle2->setZOrder(1); - particle2->setID("gauntlet-particles-2"_spr); - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("31a-1a1a0.3a23a90a90a29a0a11a0a0a0a0a0a0a0a33a1a89a149a0.454902a0a0.321569a0a0.152941a0a1a0a50a1a145a68a0.454902a0a0.321569a0a0.152941a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a1a2a1a0a0a0a192a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setPosition(gauntlet->getPosition()); - particle3->setZOrder(1); - particle3->setID("gauntlet-particles-3"_spr); - CCParticleSystemQuad* particle4 = GameToolbox::particleFromString("30a-1a2a0.3a13a90a8a21a0a8a0a0a45a0a0a0a0a40a1a89a149a0.396078a0a0.27451a0a0.14902a0a1a0a24a1a145a68a0.141176a0a0.0352941a0a0.0313726a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle4); - particle4->setPosition(gauntlet->getPosition()); - particle4->setZOrder(1); - particle4->setID("gauntlet-particles-4"_spr); - CCParticleSystemQuad* particle5 = GameToolbox::particleFromString("30a-1a1a0.3a13a90a8a21a0a0a0a0a45a0a0a0a0a21a1a89a149a0.894118a0a0.631373a0a0.345098a0a1a0a6a1a145a68a0.894118a0a0.631373a0a0.345098a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a183a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle5); - particle5->setPosition(gauntlet->getPosition()); - particle5->setZOrder(1); - particle5->setID("gauntlet-particles-5"_spr); - } else if (gauntletName == "Castle") { - CCSprite* sprite = CCSprite::create("castle_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.275f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - } else if (gauntletName == "Galaxy") { - CCSprite* sprite = CCSprite::create("galaxy_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.695f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({0, 11}); - gauntlet->setScale(0.975); - gauntlet_node->setZOrder(3); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("11a-1a1a0.3a8a90a90a0a0a0a0a0a0a0a0a0a0a50a3a0a0a0.627451a0a0.286275a0a0.470588a0a1a0a50a3a106a70a0.627451a0a0.286275a0a0.470588a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a176a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({0, 24}); - particle->setZOrder(1); - particle->setScaleX(1.610f); - particle->setScaleY(1.610f); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("14a-1a1.2a0.3a9a112a6a42a0a15a0a0a0a0a0a0a0a4a0a340a0a0.913725a0a0.72549a0a0.337255a0a1a0a4a0a340a0a0.913725a0a0.72549a0a0.337255a0a1a0a0.3a0a0.3a0a0a0a0a0a0a0a0a2a1a0a0a0a31a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition({-25, 111}); - particle2->setZOrder(1); - particle2->setScaleX(2.660f); - particle2->setScaleY(3.710f); - particle2->setRotation(180); - particle2->setID("gauntlet-particles-2"_spr); - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("38a-1a1.5a0.3a21a90a90a0a0a31a69a0a0a0a0a0a0a2a1a65a57a0.886275a0a0.866667a0a0.454902a0a1a0a5a1a0a0a0.886275a0a0.866667a0a0.454902a0a1a0a0.2a0a0.4a0a0a0a0a0a0a0a0a2a1a0a0a0a169a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setPosition({2, 6}); - particle3->setZOrder(1); - particle3->setScaleX(1.685f); - particle3->setScaleY(1.485f); - particle3->setID("gauntlet-particles-3"_spr); - CCParticleSystemQuad* particle4 = GameToolbox::particleFromString("11a-1a1.5a0.3a6a90a90a0a0a31a69a0a0a0a0a0a0a4a1a0a0a0.890196a0a0.376471a0a0.65098a0a1a0a7a1a52a55a0.890196a0a0.376471a0a0.65098a0a1a0a0.2a0a0.4a0a0a0a0a0a0a0a0a2a1a0a0a0a167a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle4); - particle4->setPosition({2, -2}); - particle4->setZOrder(1); - particle4->setScaleX(1.310f); - particle4->setScaleY(1.635f); - particle4->setID("gauntlet-particles-4"_spr); - CCParticleSystemQuad* particle5 = GameToolbox::particleFromString("4a-1a1a0.3a3a90a90a0a0a0a0a0a0a0a0a0a0a50a3a0a0a0.862745a0a0.352941a0a0.623529a0a1a0a50a3a106a22a0.862745a0a0.352941a0a0.623529a0a1a0a0.3a0a0.3a0a0a0a0a0a0a0a0a2a1a0a0a0a164a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle5); - particle5->setPosition({0, 24}); - particle5->setZOrder(1); - particle5->setScaleX(1.785f); - particle5->setScaleY(1.785f); - particle5->setID("gauntlet-particles-5"_spr); - } else if (gauntletName == "Universe") { - CCSprite* sprite = CCSprite::create("universe_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({0, 16}); - gauntlet->setScale(0.975f); - gauntlet_node->setZOrder(3); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("23a-1a3a0.3a6a90a180a29a0a11a0a0a0a0a0a0a0a38a1a0a0a0.0627451a0a0.0980392a0a0.105882a0a1a0a50a1a0a0a0.0627451a0a0.0980392a0a0.105882a0a1a0a0.1a0a0.5a0a10a0a28a0a0a0a1a2a1a0a1a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({0, 11}); - particle->setZOrder(1); - particle->setScaleX(1.485f); - particle->setScaleY(2.685f); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("20a-1a0.5a0a15a90a0a44a0a11a0a0a0a0a0a0a0a4a1a0a0a0.760784a0a0.447059a0a0.94902a0a1a0a4a1a0a0a0.760784a0a0.447059a0a0.94902a0a1a0a0.1a0a0.1a0a0a0a0a0a0a0a0a2a1a0a0a0a33a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition({32, -74}); - particle2->setZOrder(1); - particle2->setScaleX(3.685f); - particle2->setScaleY(8.310f); - particle2->setRotation(-20); - particle2->setID("gauntlet-particles-2"_spr); - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("19a-1a0.5a0a38a90a0a44a0a20a0a0a0a0a0a0a0a2a1a0a0a0.94902a0a0.67451a0a0.447059a0a1a0a2a1a0a0a0.94902a0a0.67451a0a0.447059a0a1a0a0.1a0a0.1a0a0a0a0a0a0a0a0a2a1a0a0a0a33a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setPosition({34, -96}); - particle3->setZOrder(1); - particle3->setScaleX(2.135f); - particle3->setScaleY(8.935f); - particle3->setRotation(-20); - particle3->setID("gauntlet-particles-3"_spr); - CCParticleSystemQuad* particle4 = GameToolbox::particleFromString("20a-1a1a0a15a90a0a36a0a11a0a0a0a0a0a0a0a4a1a0a0a0.447059a0a0.654902a0a0.94902a0a1a0a4a1a0a0a0.447059a0a0.654902a0a0.94902a0a1a0a0.2a0a0.2a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle4); - particle4->setPosition({41, -92}); - particle4->setZOrder(1); - particle4->setScaleX(3.235f); - particle4->setScaleY(6.585f); - particle4->setRotation(-20); - particle4->setID("gauntlet-particles-4"_spr); - CCParticleSystemQuad* particle5 = GameToolbox::particleFromString("11a-1a1a0.3a8a90a90a0a0a0a0a0a0a0a0a0a0a50a3a0a0a0.239216a0a0.403922a0a0.419608a0a1a0a50a3a106a70a0.239216a0a0.403922a0a0.419608a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a176a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle5); - particle5->setPosition({0, 24}); - particle5->setZOrder(1); - particle5->setScaleX(1.710f); - particle5->setScaleY(1.710f); - particle5->setID("gauntlet-particles-5"_spr); - CCParticleSystemQuad* particle6 = GameToolbox::particleFromString("4a-1a1a0.3a3a90a90a0a0a0a0a0a0a0a0a0a0a50a3a0a0a0.32549a0a0.537255a0a0.560784a0a1a0a50a3a106a22a0.32549a0a0.537255a0a0.560784a0a1a0a0.3a0a0.3a0a0a0a0a0a0a0a0a2a1a0a0a0a190a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle6); - particle6->setPosition({-2, 24}); - particle6->setZOrder(1); - particle6->setScaleX(2.710f); - particle6->setScaleY(2.710f); - particle6->setID("gauntlet-particles-6"_spr); - } else if (gauntletName == "Cursed") { - CCSprite* sprite = CCSprite::create("cursed_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({1, 16}); - gauntlet->setScale(1); - gauntlet_node->setZOrder(3); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("5a-1a1a0.3a3a90a90a29a0a11a0a0a0a0a0a0a0a50a1a24a45a0.105882a0a0.380392a0a0.105882a0a1a0a44a1a48a28a0.105882a0a0.380392a0a0.105882a0a1a0a0a0a0a0a0a0a0a0a0a0a1a2a1a0a0a0a175a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition(gauntlet->getPosition()); - particle->setZOrder(1); - particle->setScaleX(2.035f); - particle->setScaleY(2.035f); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("5a-1a1a0.3a3a90a90a29a0a11a0a0a0a0a0a0a0a50a1a24a45a0.105882a0a0.380392a0a0.105882a0a1a0a44a1a48a28a0.105882a0a0.380392a0a0.105882a0a1a0a0a0a0a0a0a0a0a0a0a0a1a2a1a0a0a0a175a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition(gauntlet->getPosition()); - particle2->setZOrder(1); - particle2->setScaleX(2.035f); - particle2->setScaleY(2.035f); - particle2->setID("gauntlet-particles-2"_spr); - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("93a-1a1a0.3a71a90a0a52a0a10a0a23a0a0a0a0a0a2a1a0a0a0.00392157a0a0.905882a0a0a0a1a0a2a1a30a0a0.00392157a0a0.905882a0a0a0a1a0a0.3a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a32a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setPosition({17, 94}); - particle3->setZOrder(1); - particle3->setScaleX(4.510f); - particle3->setScaleY(3.335f); - particle3->setRotation(180); - particle3->setID("gauntlet-particles-3"_spr); - } else if (gauntletName == "Doom") { - CCSprite* sprite = CCSprite::create("doom_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({0, 19}); - gauntlet->setScale(1.025f); - gauntlet_node->setZOrder(3); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("66a-1a3a0.3a20a90a27a11a0a43a83a0a0a0a0a0a0a5a1a0a0a0.733333a0a0.607843a0a0.12549a0a1a0a3a1a0a0a0.733333a0a0.470588a0a0.12549a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({0, -7}); - particle->setZOrder(1); - particle->setScaleX(1.235f); - particle->setScaleY(1.235f); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("44a-1a3a0.3a13a90a27a11a0a32a62a0a0a0a0a0a0a50a1a0a0a0.0666667a0a0.0509804a0a0.0470588a0a1a0a50a1a0a0a0.0666667a0a0.0509804a0a0.0470588a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition({0, -13}); - particle2->setZOrder(1); - particle2->setScaleX(1.310f); - particle2->setScaleY(1.435f); - particle2->setID("gauntlet-particles-2"_spr); - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("6a-1a1.9a0a3a90a17a69a0a3a0a0a-102a0a0a0a0a4a1a57a105a1a0a1a0a1a0a1a0a4a1a0a0a1a0a1a0a1a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a145a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setPosition(gauntlet->getPosition()); - particle3->setZOrder(1); - particle3->setScaleX(2.035f); - particle3->setScaleY(2.035f); - particle3->setID("gauntlet-particles-3"_spr); - } else if (gauntletName == "Split") { - CCSprite* sprite = CCSprite::create("split_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({-1, 20}); - gauntlet->setScale(0.975f); - gauntlet_node->setZOrder(2); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("48a-1a2a0.3a20a90a2a19a0a10a20a0a0a0a0a0a0a4a1a0a0a0.666667a0a0.360784a0a0.603922a0a1a0a2a1a0a0a0.666667a0a0.360784a0a0.603922a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a31a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({-28, -65}); - particle->setZOrder(1); - particle->setScaleX(2.180f); - particle->setScaleY(4.003f); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("48a-1a2a0.3a20a90a2a19a0a10a20a0a0a0a0a0a0a4a1a0a0a0.454902a0a0.215686a0a0.403922a0a1a0a2a1a0a0a0.454902a0a0.215686a0a0.403922a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition({-28, -65}); - particle2->setZOrder(1); - particle2->setScaleX(2.180f); - particle2->setScaleY(4.003f); - particle2->setID("gauntlet-particles-2"_spr); - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("48a-1a2a0.3a20a90a2a19a0a10a20a0a0a0a0a0a0a4a1a0a0a0.243137a0a0.329412a0a0.341176a0a1a0a2a1a0a0a0.243137a0a0.329412a0a0.341176a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a31a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setPosition({25, 65}); - particle3->setZOrder(1); - particle3->setScaleX(2.180f); - particle3->setScaleY(4.003f); - particle3->setRotation(180); - particle3->setID("gauntlet-particles-3"_spr); - CCParticleSystemQuad* particle4 = GameToolbox::particleFromString("48a-1a2a0.3a20a90a2a19a0a10a20a0a0a0a0a0a0a4a1a0a0a0.145098a0a0.203922a0a0.207843a0a1a0a2a1a0a0a0.145098a0a0.203922a0a0.207843a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle4); - particle4->setPosition({25, 65}); - particle4->setZOrder(1); - particle4->setScaleX(2.180f); - particle4->setScaleY(4.003f); - particle4->setRotation(180); - particle4->setID("gauntlet-particles-4"_spr); - CCParticleSystemQuad* particle5 = GameToolbox::particleFromString("30a-1a2a0.3a13a90a90a29a0a11a0a0a0a0a0a0a0a6a1a0a0a0.705882a0a0.34902a0a0.698039a0a1a0a2a1a0a0a0.584314a0a0.34902a0a0.705882a0a1a0a0a0a0.5a0a6a0a34a0a0a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle5); - particle5->setPosition({0, 29}); - particle5->setZOrder(1); - particle5->setScaleX(1.955f); - particle5->setScaleY(1.955f); - particle5->setRotation(90); - particle5->setID("gauntlet-particles-5"_spr); - CCParticleSystemQuad* particle6 = GameToolbox::particleFromString("30a-1a2a0.3a13a90a90a29a0a11a0a0a0a0a0a0a0a6a1a0a0a0.254902a0a0.333333a0a0.388235a0a1a0a2a1a0a0a0.254902a0a0.333333a0a0.388235a0a1a0a0a0a0.5a0a6a0a34a0a0a0a1a2a1a0a0a0a159a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle6); - particle6->setPosition({0, 29}); - particle6->setZOrder(1); - particle6->setScaleX(1.955f); - particle6->setScaleY(1.955f); - particle6->setRotation(-90); - particle6->setID("gauntlet-particles-6"_spr); - CCParticleSystemQuad* particle7 = GameToolbox::particleFromString("30a-1a2a0.3a13a90a90a29a0a11a0a0a0a0a0a0a0a6a1a0a0a0.705882a0a0.34902a0a0.698039a0a1a0a2a1a0a0a0.584314a0a0.34902a0a0.705882a0a1a0a0a0a0.5a0a6a0a34a0a0a0a1a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle7); - particle7->setPosition({0, 29}); - particle7->setZOrder(1); - particle7->setScaleX(1.955f); - particle7->setScaleY(1.955f); - particle7->setRotation(90); - particle7->setID("gauntlet-particles-7"_spr); - CCParticleSystemQuad* particle8 = GameToolbox::particleFromString("30a-1a2a0.3a13a90a90a29a0a11a0a0a0a0a0a0a0a6a1a0a0a0.254902a0a0.333333a0a0.388235a0a1a0a2a1a0a0a0.254902a0a0.333333a0a0.388235a0a1a0a0a0a0.5a0a6a0a34a0a0a0a1a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle8); - particle8->setPosition({0, 29}); - particle8->setZOrder(1); - particle8->setScaleX(1.955f); - particle8->setScaleY(1.955f); - particle8->setRotation(-90); - particle8->setID("gauntlet-particles-8"_spr); - } else if (gauntletName == "Monster") { - CCSprite* sprite = CCSprite::create("monster_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({0, 22}); - gauntlet->setScale(1.075f); - gauntlet_node->setZOrder(2); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("30a-1a3a0.3a9a90a9a11a0a17a40a0a0a0a0a0a0a4a1a0a0a0.0509804a0a0.929412a0a0a0a1a0a2a1a0a0a0.360784a0a0.486275a0a0.352941a0a1a0a0.1a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a165a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({gauntlet->getPositionX(), -37}); - particle->setZOrder(1); - particle->setScaleX(2.510f); - particle->setScaleY(1.985f); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("66a-1a3a0.3a20a90a27a11a0a37a38a0a0a0a0a0a0a5a1a0a0a0.0156863a0a0.866667a0a0.027451a0a1a0a3a1a0a0a0.164706a0a0.509804a0a0a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition({gauntlet->getPositionX(), -38}); - particle2->setZOrder(1); - particle2->setScaleX(1.072f); - particle2->setScaleY(2.475f); - particle2->setID("gauntlet-particles-2"_spr); - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("18a-1a3a0.3a5a90a9a11a0a32a28a0a0a0a0a0a0a50a1a0a0a0.0352941a0a0.0901961a0a0.0313726a0a1a0a50a1a0a0a0.0352941a0a0.0901961a0a0.0313726a0a1a0a1a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setPosition({gauntlet->getPositionX(), -48}); - particle3->setZOrder(1); - particle3->setScaleX(1.470f); - particle3->setScaleY(1.957f); - particle3->setID("gauntlet-particles-3"_spr); - } else if (gauntletName == "Mystery") { - CCSprite* sprite = CCSprite::create("mystery_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({3, 13}); - gauntlet->setScale(0.975f); - gauntlet_node->setZOrder(3); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("30a-1a3a0.3a9a90a180a29a0a11a0a0a0a0a0a0a0a2a1a0a0a1a0a0.8a0a0.258824a0a1a0a8a1a0a0a1a0a0.8a0a0.258824a0a1a0a0.5a0a0.5a0a6a0a30a0a0a0a1a2a0a0a0a0a11a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition(gauntlet->getPosition()); - particle->setZOrder(2); - particle->setScaleX(2.035f); - particle->setScaleY(2.035f); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("31a-1a3a0.3a9a90a180a0a0a29a82a0a0a0a0a0a0a4a1a0a0a0.388235a0a0.741176a0a1a0a1a0a15a1a0a0a0.388235a0a0.741176a0a1a0a1a0a1a0a1a0a6a0a30a0a0a0a0a2a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition({0, 0}); - particle2->setZOrder(1); - particle2->setScaleX(1.435f); - particle2->setScaleY(1.435f); - particle2->setID("gauntlet-particles-2"_spr); - } else if (gauntletName == "Strange") { - CCSprite* sprite = CCSprite::create("strange_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - reverseGauntlet(node); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({2, -18}); - gauntlet->setRotation(180); - gauntlet->setScale(0.975f); - gauntlet->setFlipX(true); - gauntlet_node->setZOrder(2); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("36a-1a3a0.3a6a-90a24a9a0a11a0a0a-7a0a0a0a0a2a1a76a325a0.592157a0a0.294118a0a0.658824a0a1a0a2a1a201a149a0.592157a0a0.294118a0a0.658824a0a1a0a0.3a0a0.3a0a0a0a0a0a0a0a0a2a0a0a0a0a96a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({2, -65}); - particle->setZOrder(2); - particle->setScaleX(2.480f); - particle->setScaleY(2.728f); - particle->setRotation(180); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("17a-1a4a0.3a3a180a0a8a0a47a34a0a0a0a0a0a0a50a1a0a0a0.243137a0a0.239216a0a0.239216a0a1a0a50a1a0a0a0.454902a0a0.447059a0a0.447059a0a1a0a1a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition({17, 60}); - particle2->setZOrder(3); - particle2->setScaleX(0.805f); - particle2->setScaleY(1.155f); - particle2->setID("gauntlet-particles-2"_spr); - } else if (gauntletName == "Water") { - CCSprite* sprite = CCSprite::create("water_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - } else if (gauntletName == "Fire") { - CCSprite* sprite = CCSprite::create("fire_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({0, 15}); - gauntlet->setScale(1.050f); - gauntlet_node->setZOrder(2); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("30a-1a2a0.3a13a90a8a21a0a8a0a0a45a0a0a0a0a50a1a89a149a0.396078a0a0.27451a0a0.14902a0a1a0a31a1a145a68a0.141176a0a0.0352941a0a0.0313726a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({-1, 0}); - particle->setZOrder(1); - particle->setScaleX(1.435f); - particle->setScaleY(0.935f); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("30a-1a1a0.3a13a90a8a21a0a0a0a0a45a0a0a0a0a21a1a89a149a0.894118a0a0.631373a0a0.345098a0a1a0a13a1a145a68a0.894118a0a0.631373a0a0.345098a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a183a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition(gauntlet->getPosition()); - particle2->setZOrder(1); - particle2->setScaleX(2.322f); - particle2->setScaleY(1.347f); - particle2->setID("gauntlet-particles-2"_spr); - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("19a-1a2a0.3a8a90a0a29a0a5a0a0a0a0a0a0a0a50a1a50a33a0.12549a0a0.0862745a0a0a0a1a0a30a1a50a30a0.12549a0a0.0862745a0a0a0a1a0a0.1a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a181a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setPosition(gauntlet->getPosition()); - particle3->setZOrder(1); - particle3->setScaleX(1.145f); - particle3->setScaleY(1.795f); - particle3->setID("gauntlet-particles-3"_spr); - CCParticleSystemQuad* particle4 = GameToolbox::particleFromString("31a-1a3a0.3a9a90a27a11a0a37a38a0a0a0a0a0a0a50a1a0a0a0.133333a0a0.0862745a0a0.0588235a0a1a0a50a1a0a0a0.0666667a0a0.0470588a0a0.0352941a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle4); - particle4->setPosition({1, -23}); - particle4->setZOrder(1); - particle4->setScaleX(1.270f); - particle4->setScaleY(1.832f); - particle4->setID("gauntlet-particles-4"_spr); - CCParticleSystemQuad* particle5 = GameToolbox::particleFromString("40a-1a3a0.3a12a90a13a11a0a48a78a0a0a0a0a0a0a5a3a0a0a0.439216a0a0.309804a0a0.129412a0a1a0a3a3a0a0a0.439216a0a0.309804a0a0.129412a0a1a0a0.1a0a0.3a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle5); - particle5->setPosition({2, -20}); - particle5->setZOrder(1); - particle5->setScaleX(1.205f); - particle5->setScaleY(1.280f); - particle5->setID("gauntlet-particles-5"_spr); - } else if (gauntletName == "Ice") { - CCSprite* sprite = CCSprite::create("ice_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({0, 15}); - gauntlet->setScale(1.050f); - gauntlet_node->setZOrder(2); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("25a-1a1a0.3a19a90a90a0a0a0a0a0a0a0a0a0a0a12a1a0a98a0.0980392a0a0.176471a0a0.219608a0a1a0a36a1a0a0a0.0980392a0a0.176471a0a0.219608a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a191a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({0, 17}); - particle->setZOrder(1); - particle->setScaleX(3.760f); - particle->setScaleY(3.760f); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("200a-1a4a0.3a46a90a0a18a0a24a0a0a0a0a0a0a0a1a1a0a39a0.980392a0a1a0a0.980392a0a1a0a1a1a98a41a0.980392a0a1a0a0.980392a0a1a0a0.3a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a14a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition({11, 112}); - particle2->setZOrder(1); - particle2->setScaleX(2.322f); - particle2->setScaleY(3.097f); - particle2->setRotation(-174); - particle2->setID("gauntlet-particles-2"_spr); - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("44a-1a3a0.3a13a90a27a11a0a40a62a0a0a0a0a0a0a50a1a0a0a0.0431373a0a0.0627451a0a0.0666667a0a1a0a50a1a0a0a0.0431373a0a0.0627451a0a0.0666667a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setPosition({0, -11}); - particle3->setZOrder(1); - particle3->setScaleX(1.145f); - particle3->setScaleY(1.795f); - particle3->setID("gauntlet-particles-3"_spr); - CCParticleSystemQuad* particle4 = GameToolbox::particleFromString("38a-1a1.5a0.3a21a90a90a0a0a31a69a0a0a0a0a0a0a2a1a65a57a1a0a1a0a1a0a1a0a5a1a0a0a1a0a1a0a1a0a1a0a0.2a0a0.4a0a0a0a0a0a0a0a0a2a1a0a0a0a169a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle4); - particle4->setPosition(gauntlet->getPosition()); - particle4->setZOrder(1); - particle4->setScaleX(1.470f); - particle4->setScaleY(1.957f); - particle4->setID("gauntlet-particles-4"_spr); - } else if (gauntletName == "Poison") { - CCSprite* sprite = CCSprite::create("poison_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("31a-1a3a0.3a9a90a27a11a0a37a64a0a0a0a0a0a0a50a1a0a0a0.054902a0a0.129412a0a0.0627451a0a1a0a50a1a0a0a0.054902a0a0.129412a0a0.0627451a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({0, 11}); - particle->setZOrder(1); - particle->setScaleX(1.260f); - particle->setScaleY(1.485f); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("20a-1a3a0.3a6a90a22a11a0a33a55a0a0a0a0a0a0a1a1a0a0a0.137255a0a0.301961a0a0.133333a0a1a0a10a1a0a0a0.137255a0a0.301961a0a0.133333a0a1a0a0.1a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a40a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition({-3, -13}); - particle2->setZOrder(1); - particle2->setScaleX(1.722f); - particle2->setScaleY(1.397f); - particle2->setID("gauntlet-particles-2"_spr); - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("4a-1a2.5a0.3a1a-90a0a0a10a35a0a0a-70a0a0a0a0a6a2a140a0a0.345098a0a0.690196a0a0.301961a0a1a0a4a2a140a0a0.345098a0a0.690196a0a0.301961a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a77a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setPosition({0, 109}); - particle3->setZOrder(1); - particle3->setScaleX(1.145f); - particle3->setScaleY(1.795f); - particle3->setID("gauntlet-particles-3"_spr); - CCParticleSystemQuad* particle4 = GameToolbox::particleFromString("40a-1a3a0.3a12a90a13a11a0a48a78a0a0a0a0a0a0a3a1a0a0a0.129412a0a0.439216a0a0.168627a0a1a0a1a1a0a0a0.129412a0a0.439216a0a0.168627a0a1a0a0.1a0a0.3a0a0a0a0a0a0a0a0a2a1a0a0a0a192a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle4); - particle4->setPosition(gauntlet->getPosition()); - particle4->setZOrder(1); - particle4->setScaleX(1.270f); - particle4->setScaleY(1.632f); - particle4->setID("gauntlet-particles-4"_spr); - } else if (gauntletName == "Shadow") { - CCSprite* sprite = CCSprite::create("shadow_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.745f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({2, 26}); - gauntlet->setScale(0.975f); - gauntlet_node->setZOrder(2); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("48a-1a3a0.3a14a90a27a6a0a40a57a0a0a0a0a0a0a50a1a0a0a0.0509804a0a0.0235294a0a0.0666667a0a1a0a50a1a0a0a0.0509804a0a0.0235294a0a0.0666667a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({0, -15}); - particle->setZOrder(1); - particle->setScaleX(1.310f); - particle->setScaleY(1.735f); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("62a-1a1a0.3a47a90a90a29a0a11a0a0a0a0a0a0a0a50a1a0a59a0.0784314a0a0.0235294a0a0.0941176a0a1a0a38a1a103a65a0.0784314a0a0.0235294a0a0.0941176a0a1a0a0.5a0a0.5a0a0a0a0a0a0a0a1a2a1a0a0a0a190a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition({0, 25}); - particle2->setZOrder(1); - particle2->setScaleX(2.472f); - particle2->setScaleY(2.472f); - particle2->setID("gauntlet-particles-2"_spr); - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("62a-1a1a0.3a47a90a180a29a0a11a0a0a0a0a0a0a0a50a1a0a0a0.0313726a0a0.00392157a0a0.0470588a0a1a0a38a1a0a0a0.0313726a0a0.00392157a0a0.0470588a0a1a0a0.5a0a0.5a0a38a0a9a0a-85a26a1a2a1a0a0a0a183a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setPosition({0, 25}); - particle3->setZOrder(1); - particle3->setScaleX(1.470f); - particle3->setScaleY(1.470f); - particle3->setID("gauntlet-particles-3"_spr); - CCParticleSystemQuad* particle4 = GameToolbox::particleFromString("62a-1a1a0.3a47a90a180a29a0a11a0a0a0a0a0a0a0a50a1a0a0a0.0313726a0a0.00392157a0a0.0431373a0a1a0a38a1a0a0a0.0313726a0a0.00392157a0a0.0431373a0a1a0a0.5a0a0.5a0a38a0a9a0a-85a26a1a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle4); - particle4->setPosition({0, 25}); - particle4->setZOrder(1); - particle4->setScaleX(1.195f); - particle4->setScaleY(1.195f); - particle4->setID("gauntlet-particles-4"_spr); - CCParticleSystemQuad* particle5 = GameToolbox::particleFromString("40a-1a3a0.3a12a90a13a11a0a48a78a0a0a0a0a0a0a5a3a0a0a0.129412a0a0.439216a0a0.133333a0a1a0a3a3a0a0a0.129412a0a0.439216a0a0.133333a0a1a0a0.1a0a0.3a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle5); - particle5->setPosition({0, -16}); - particle5->setZOrder(1); - particle5->setScaleX(1.255f); - particle5->setScaleY(1.430f); - particle5->setID("gauntlet-particles-5"_spr); - } else if (gauntletName == "Lava") { - CCSprite* sprite = CCSprite::create("lava_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({0, 16}); - gauntlet->setScale(0.950f); - gauntlet_node->setZOrder(2); - - // Particle - CCParticleSystemQuad* particle = GameToolbox::particleFromString("40a-1a3a0.3a12a90a13a11a0a48a78a0a0a0a0a0a0a5a3a0a0a0.439216a0a0.309804a0a0.129412a0a1a0a3a3a0a0a0.439216a0a0.309804a0a0.129412a0a1a0a0.1a0a0.3a0a0a0a0a0a0a0a0a2a1a0a0a0a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({0, -16}); - particle->setZOrder(1); - particle->setScaleX(1.360f); - particle->setScaleY(1.360f); - particle->setID("gauntlet-particles-1"_spr); - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("59a-1a1a0.3a45a90a14a100a54a2a6a0a-135a0a46a0a0a20a8a0a0a1a0a0.756863a0a0.258824a0a1a0a1a1a0a0a1a0a0.694118a0a0.321569a0a1a0a0a0a0.1a0a0a0a0a0a0a0a0a2a1a0a0a1a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition(gauntlet->getPosition()); - particle2->setZOrder(1); - particle2->setScaleX(1.522f); - particle2->setScaleY(1.547f); - particle2->setID("gauntlet-particles-2"_spr); - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("56a-1a1a0.3a43a90a16a103a81a2a6a0a-180a0a46a0a0a13a8a0a0a1a0a0.756863a0a0.258824a0a1a0a1a1a0a0a1a0a0.694118a0a0.321569a0a1a0a0a0a0.1a0a0a0a0a0a0a0a0a2a1a0a0a1a28a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setPosition(gauntlet->getPosition()); - particle3->setZOrder(1); - particle3->setScaleX(1.470f); - particle3->setScaleY(1.370f); - particle3->setID("gauntlet-particles-3"_spr); - CCParticleSystemQuad* particle4 = GameToolbox::particleFromString("56a-1a1a0.5a19a90a28a49a43a2a6a0a23a0a43a0a0a50a33a0a0a0.172549a0a0.160784a0a0.14902a0a0.47a0a50a38a0a0a0.247059a0a0.243137a0a0.239216a0a0.47a0a0a0a0.13a0a0a0a0a0a0a0a0a2a0a0a0a1a29a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle4); - particle4->setPosition(gauntlet->getPosition()); - particle4->setZOrder(1); - particle4->setScaleX(1.095f); - particle4->setScaleY(0.845f); - particle4->setID("gauntlet-particles-4"_spr); - CCParticleSystemQuad* particle5 = GameToolbox::particleFromString("59a-1a1a0.3a45a90a18a113a30a2a6a0a-192a0a46a0a0a20a8a0a0a1a0a0.505882a0a0.258824a0a1a0a1a1a0a0a1a0a0.505882a0a0.258824a0a1a0a0a0a0.1a0a0a0a0a0a0a0a0a2a1a0a0a1a158a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle5); - particle5->setPosition(gauntlet->getPosition()); - particle5->setZOrder(1); - particle5->setScaleX(1.255f); - particle5->setScaleY(1.430f); - particle5->setID("gauntlet-particles-5"_spr); - CCParticleSystemQuad* particle6 = GameToolbox::particleFromString("48a-1a3a0.3a14a90a27a6a0a40a57a0a0a0a0a0a0a50a1a0a0a0.0666667a0a0.0352941a0a0.0196078a0a1a0a50a1a0a0a0.0666667a0a0.0352941a0a0.0196078a0a1a0a0.5a0a1a0a0a0a0a0a0a0a0a2a1a0a0a0a46a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle6); - particle6->setPosition({0, -18}); - particle6->setZOrder(1); - particle6->setScaleX(1.235f); - particle6->setScaleY(1.835f); - particle6->setID("gauntlet-particles-6"_spr); - } else if (gauntletName == "Time") { - CCSprite* sprite = CCSprite::create("time_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.220f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - } else if (gauntletName == "Spike") { - CCSprite* sprite = CCSprite::create("spike_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.920f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - } else if (gauntletName == "Cyborg") { - CCSprite* sprite = CCSprite::create("cyborg_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - } else if (gauntletName == "Inferno") { - CCSprite* sprite = CCSprite::create("inferno_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - } else if (gauntletName == "Death") { - CCSprite* sprite = CCSprite::create("death_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - } else if (gauntletName == "Magic") { - CCSprite* sprite = CCSprite::create("magic_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - } else if (gauntletName == "Chaos") { - CCSprite* sprite = CCSprite::create("chaos_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - } else if (gauntletName == "Force") { - CCSprite* sprite = CCSprite::create("force_gauntlet.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - } else if (gauntletName == "NCS I") { - CCSprite* sprite = CCSprite::create("ncs_gauntlet_1.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({0, 16}); - gauntlet->setScale(0.9f); - gauntlet_node->setZOrder(3); - - CCParticleSystemQuad* particle = GameToolbox::particleFromString("25a-1a1a0.3a19a90a90a0a0a0a0a0a0a0a0a0a0a23a1a0a98a0.0980392a0a0.176471a0a0.219608a0a1a0a50a1a0a0a0.0980392a0a0.176471a0a0.219608a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a185a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({0, 20}); - particle->setZOrder(2); - particle->setScale(2.060f); - particle->setID("gauntlet-particles-1"_spr); - - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("25a-1a1a0.3a19a90a90a0a0a0a0a0a0a0a0a0a0a12a1a0a98a0.0980392a0a0.176471a0a0.219608a0a1a0a36a1a0a0a0.0980392a0a0.176471a0a0.219608a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a167a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition(gauntlet->getPosition()); - particle2->setZOrder(2); - particle2->setScale(4.210f); - particle2->setID("gauntlet-particles-2"_spr); - - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("30a-1a2.5a0.3a10a90a12a19a0a23a0a0a11a0a0a0a0a4a1a0a0a0.313726a0a0.458824a0a0.529412a0a1a0a2a1a0a0a0.313726a0a0.458824a0a0.529412a0a1a0a0a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a19a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setZOrder(0); - particle3->setPosition({0, -81}); - particle3->setScale(2.035f); - particle3->setID("gauntlet-particles-3"_spr); - } else if (gauntletName == "NCS II") { - CCSprite* sprite = CCSprite::create("ncs_gauntlet_2.png"_spr); - sprite->setPosition(bg->getPosition()); - sprite->setScale(1.270f/scaleFactor); - sprite->setZOrder(0); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - - // Show gauntlets sprite again - gauntlet->setVisible(true); - gauntlet->setPosition({0, 16}); - gauntlet->setScale(0.9f); - gauntlet_node->setZOrder(3); - - CCParticleSystemQuad* particle = GameToolbox::particleFromString("25a-1a1a0.3a19a90a90a0a0a0a0a0a0a0a0a0a0a23a1a0a98a0.301961a0a0.156863a0a0.341176a0a1a0a50a1a0a0a0.301961a0a0.156863a0a0.341176a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a185a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle); - particle->setPosition({0, 20}); - particle->setZOrder(2); - particle->setScale(2.060f); - particle->setID("gauntlet-particles-1"_spr); - - CCParticleSystemQuad* particle2 = GameToolbox::particleFromString("25a-1a1a0.3a19a90a90a0a0a0a0a0a0a0a0a0a0a12a1a0a98a0.301961a0a0.156863a0a0.341176a0a1a0a36a1a0a0a0.301961a0a0.156863a0a0.341176a0a1a0a0a0a0a0a0a0a0a0a0a0a0a2a1a0a0a0a167a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle2); - particle2->setPosition(gauntlet->getPosition()); - particle2->setZOrder(2); - particle2->setScale(4.210f); - particle2->setID("gauntlet-particles-2"_spr); - - CCParticleSystemQuad* particle3 = GameToolbox::particleFromString("30a-1a2.5a0.3a10a90a12a19a0a23a0a0a11a0a0a0a0a4a1a0a0a0.482353a0a0.317647a0a0.533333a0a1a0a2a1a0a0a0.482353a0a0.317647a0a0.533333a0a1a0a0a0a0.5a0a0a0a0a0a0a0a0a2a1a0a0a0a19a0a0a0a0a0a0a0a0a0a0a0a0a0a0", NULL, false); - node->addChild(particle3); - particle3->setZOrder(0); - particle3->setPosition({0, -81}); - particle3->setScale(2.035f); - particle3->setID("gauntlet-particles-3"_spr); - } else if (gauntletName == "Discord") { - CCSprite* sprite = CCSprite::create("discord_gauntlet.png"_spr); - sprite->setPosition({bg->getPositionX(), bg->getPositionY() + 3}); - sprite->setScale(1.245f/scaleFactor); - sprite->setZOrder(0); - item->setZOrder(1); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - } else if (gauntletName == "Space") { - CCSprite* sprite = CCSprite::create("space_gauntlet.png"_spr); - sprite->setPosition({bg->getPositionX(), bg->getPositionY() + 3}); - sprite->setScale(1.245f/scaleFactor); - sprite->setZOrder(0); - item->setZOrder(1); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - } else if (gauntletName == "Cosmos") { - CCSprite* sprite = CCSprite::create("cosmos_gauntlet.png"_spr); - sprite->setPosition({bg->getPositionX(), bg->getPositionY() + 3}); - sprite->setScale(1.245f/scaleFactor); - sprite->setZOrder(0); - item->setZOrder(1); - sprite->setID("gauntlet-background"_spr); - node->addChild(sprite); - } else { - bg->setVisible(true); - label->setVisible(true); - label_shadow->setVisible(true); - label_gauntlet->setVisible(true); - label_shadow_gauntlet->setVisible(true); - gauntlet->setVisible(true); - gauntlet_shadow->setVisible(true); - } - } - } - } -}; diff --git a/src/Styles/IconLockColors.cpp b/src/Styles/IconLockColors.cpp deleted file mode 100644 index a930cc4..0000000 --- a/src/Styles/IconLockColors.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "../includes.h" -#include -#include -#ifndef GEODE_IS_IOS -class IconLockColors { - public: - void onP1(CCObject* pSender) { - SimplePlayer* player = this->getPlayer(CCDirector::sharedDirector()->getRunningScene()); - - GameManager* gm = GameManager::sharedState(); - player->setColor(gm->colorForIdx(gm->getPlayerColor())); - player->setSecondColor(gm->colorForIdx(gm->getPlayerColor2())); - }; - - void onP2(CCObject* pSender) { - SimplePlayer* player = this->getPlayer(CCDirector::sharedDirector()->getRunningScene()); - - GameManager* gm = GameManager::sharedState(); - player->setColor(gm->colorForIdx(gm->getPlayerColor2())); - player->setSecondColor(gm->colorForIdx(gm->getPlayerColor())); - }; - - void onGlow(CCObject* pSender) { - SimplePlayer* player = this->getPlayer(CCDirector::sharedDirector()->getRunningScene()); - GameManager* gm = GameManager::sharedState(); - - if (!player->m_hasGlowOutline) { - player->setGlowOutline(gm->colorForIdx(gm->getPlayerGlowColor())); - } else { - player->disableGlowOutline(); - } - }; - - static SimplePlayer* getPlayer(CCScene* scene) { - CCArray* children = scene->getChildren(); - - for (int i = 0; i < children->count(); i++) { - ItemInfoPopup* child = typeinfo_cast(children->objectAtIndex(i)); - - if (child) { - CCArray* array_childrens = typeinfo_cast(child->getChildren()->objectAtIndex(0))->getChildren(); - - for (int j = 0; j < array_childrens->count(); j++) { - GJItemIcon* node = typeinfo_cast(array_childrens->objectAtIndex(j)); - - if (node) { - SimplePlayer* player = typeinfo_cast(node->getChildren()->objectAtIndex(0)); - return player; - } - } - } - } - - return nullptr; - } - - static void createIconColor() { - auto scene = CCDirector::sharedDirector()->getRunningScene(); - CCArray* children = scene->getChildren(); - - for (int i = 0; i < children->count(); i++) { - ItemInfoPopup* child = typeinfo_cast(children->objectAtIndex(i)); - - if (child) { - CCArray* array_childrens = typeinfo_cast(child->getChildren()->objectAtIndex(0))->getChildren(); - - SimplePlayer* player = getPlayer(CCDirector::sharedDirector()->getRunningScene()); - GameManager* gm = GameManager::sharedState(); - if (player) { - player->setColor(gm->colorForIdx(gm->getPlayerColor())); - player->setSecondColor(gm->colorForIdx(gm->getPlayerColor2())); - player->m_glowColor = gm->colorForIdx(gm->getPlayerGlowColor()); - - // Creating buttons - auto p1Spr = CCSprite::createWithSpriteFrameName("GJ_checkOff_001.png"); - auto p1txt = CCLabelBMFont::create("P1", "bigFont.fnt"); - p1txt->setScale(.525f); - p1txt->setPosition(15, 17); - p1Spr->addChild(p1txt); - p1Spr->setScale(.8f); - auto p1Btn = CCMenuItemSpriteExtra::create( - p1Spr, - child, - menu_selector(IconLockColors::onP1) - ); - p1Btn->setPosition(-128, -40); - p1Btn->setID("p1-button"_spr); - child->m_buttonMenu->addChild(p1Btn); - - auto p2Spr = CCSprite::createWithSpriteFrameName("GJ_checkOff_001.png"); - auto p2txt = CCLabelBMFont::create("P2", "bigFont.fnt"); - p2txt->setScale(.525f); - p2txt->setPosition(15, 17); - p2Spr->addChild(p2txt); - p2Spr->setScale(.8f); - auto p2Btn = CCMenuItemSpriteExtra::create( - p2Spr, - child, - menu_selector(IconLockColors::onP2) - ); - p2Btn->setPosition(-99, -40); - p2Btn->setID("p2-button"_spr); - child->m_buttonMenu->addChild(p2Btn); - - auto glowSpr = CCSprite::createWithSpriteFrameName("GJ_checkOff_001.png"); - auto glowtxt = CCLabelBMFont::create("G", "bigFont.fnt"); - glowtxt->setScale(.525f); - glowtxt->setPosition(15, 17); - glowSpr->addChild(glowtxt); - glowSpr->setScale(.8f); - auto glowBtn = CCMenuItemSpriteExtra::create( - glowSpr, - child, - menu_selector(IconLockColors::onGlow) - ); - glowBtn->setPosition(-69, -40); - glowBtn->setID("glow-button"_spr); - child->m_buttonMenu->addChild(glowBtn); - } - } - } - } -}; - -class $modify(GJGarageLayer) { - void onSelect(cocos2d::CCObject* sender) { - GJGarageLayer::onSelect(sender); - - if (!Mod::get()->template getSettingValue("previewIcons")) return; - - IconLockColors::createIconColor(); - } -}; -#endif diff --git a/src/Styles/NewGJCommentList.cpp b/src/Styles/NewGJCommentList.cpp deleted file mode 100644 index cac42c8..0000000 --- a/src/Styles/NewGJCommentList.cpp +++ /dev/null @@ -1,216 +0,0 @@ -#include "NewGJCommentList.h" -#include "Geode/loader/Log.hpp" -#include "NewProfilePage.h" -#include "../MoreLeaderboards/MoreLeaderboards.h" -#include "ccTypes.h" -#include -#include -#include - -std::string badgesDataComments = ""; - -int hexStringToInt(const std::string& hexStr) { - int value; - std::istringstream iss(hexStr); - iss >> std::hex >> value; - return value; -} - -// Mod badges descriptions & GDUtils dev badge -class $modify(CommentCell) { - struct Fields { - EventListener m_listener; - }; - - void badgeHandle(std::string result, CCLayer* layer, int commentID) { - if (this->m_accountComment) return; - - CommentCell* cell = this; - int accountID = cell->m_comment->m_accountID; - - // Part for handling GDUtils badges - if (!Mod::get()->template getSettingValue("customBadges")) return; - - if (result.empty()) return; - - std::string data = result; - std::vector data_user = MoreLeaderboards::getWords(data, "|"); - - CCMenu* username_menu = typeinfo_cast(cell->getChildByIDRecursive("username-menu")); - - bool colorSet = false; - - while (data_user.size() > 0) { - std::vector data = MoreLeaderboards::getWords(data_user[0], "?"); - - int badge = 0; - int accountID_data = 0; - std::string badge_id = ""; - std::string badge_sprite = ""; - float badge_scale = 1.0f; - std::string alertTitle = ""; - std::string alertDesc = ""; - float alertWidth = 300.0f; - bool isKofi = false; - ccColor3B color = { 255, 255, 255 }; - - while (data.size() > 0) { - std::string id = data[0]; - std::string name = data[1]; - - if (id == "1") { - accountID_data = geode::utils::numFromString(name).unwrapOrDefault(); - } else if (id == "3") { - badge = geode::utils::numFromString(name).unwrapOrDefault(); - } else if (id == "4") { - badge_sprite = name; - } else if (id == "5") { - badge_id = name; - } else if (id == "7") { - badge_scale = geode::utils::numFromString(name).unwrapOrDefault(); - } else if (id == "8") { - alertTitle = name; - } else if (id == "9") { - alertDesc = name; - } else if (id == "10") { - alertWidth = geode::utils::numFromString(name).unwrapOrDefault(); - } else if (id == "11") { - isKofi = name == "1"; - } else if (id == "12") { - // Get color from HEX - color = ccc3( - hexStringToInt(name.substr(0, 2)), - hexStringToInt(name.substr(2, 2)), - hexStringToInt(name.substr(4, 2)) - ); - } - - data.erase(data.begin()); - data.erase(data.begin()); - } - - if (accountID_data == accountID) { - if (!cell->getChildByIDRecursive(badge_id)) { - auto badgeGDUtil = CCSprite::createWithSpriteFrameName(fmt::format("{}"_spr, badge_sprite).c_str()); - badgeGDUtil->setScale(badge_scale); - auto badgeGDUtilBtn = CCMenuItemSpriteExtra::create( - badgeGDUtil, - cell, - menu_selector(NewProfilePage::badgeFactoryAlert) - ); - - if (auto commentText = cell->getChildByIDRecursive("comment-text-label")) { - if (color.r != 255 && color.g != 255 && color.b != 255 && !colorSet) { - as(commentText)->setColor(color); - cell->m_comment->m_color = color; - colorSet = true; - } - } - if (auto commentText = cell->getChildByIDRecursive("comment-text-area")) { - TextArea* textArea = as(commentText); - MultilineBitmapFont* bmFont = as(textArea->getChildren()->objectAtIndex(0)); - CCArray* children = bmFont->getChildren(); - for (int i = 0; i < children->count(); i++) { - auto child = as(children->objectAtIndex(i)); - if (color.r != 255 && color.g != 255 && color.b != 255 && !colorSet) { - child->setColor(color); - colorSet = true; - } - } - } - - badgeGDUtilBtn->setID(badge_id); - - auto array = CCArray::create(); - array->addObject(CCString::create(alertTitle)); - array->addObject(CCString::create(alertDesc)); - array->addObject(CCFloat::create(alertWidth)); - array->addObject(CCString::create(isKofi ? "1" : "0")); - badgeGDUtilBtn->setUserObject(array); - - if (cell->getChildByIDRecursive("percentage-label")) { - username_menu->insertBefore(badgeGDUtilBtn, cell->getChildByIDRecursive("percentage-label")); - } else { - username_menu->addChild(badgeGDUtilBtn); - } - username_menu->updateLayout(); - } - } - - data_user.erase(data_user.begin()); - } - } - - void loadFromComment(GJComment* comment) { - CommentCell::loadFromComment(comment); - - if (comment->m_commentDeleted) return; - - CCMenuItemSpriteExtra* badgeBtn = nullptr; - CommentCell* cell = this; - CCSprite* modbadge = typeinfo_cast(cell->getChildByIDRecursive("mod-badge")); - std::string username = cell->m_comment->m_userName; - CCMenu* username_menu = typeinfo_cast(cell->getChildByIDRecursive("username-menu")); - - if (modbadge != nullptr) { - modbadge->removeFromParentAndCleanup(true); - - if (username == "RobTop" && Mod::get()->template getSettingValue("customBadges")) { - auto robtopSpr = CCSprite::createWithSpriteFrameName("robtop_badge.png"_spr); - robtopSpr->setScale(0.75f); - badgeBtn = CCMenuItemSpriteExtra::create( - robtopSpr, - this, - menu_selector(NewProfilePage::onRobTopBadgePressed) - ); - } else { - CCSprite* modSprite; - if (comment->m_modBadge == 1) { - modSprite = CCSprite::createWithSpriteFrameName("modBadge_01_001.png"); - } else if (comment->m_modBadge == 2) { - modSprite = CCSprite::createWithSpriteFrameName("modBadge_02_001.png"); - } else if (comment->m_modBadge == 3) { - modSprite = CCSprite::createWithSpriteFrameName("modBadge_03_001.png"); - } - modSprite->setScale(0.6f); - - badgeBtn = CCMenuItemSpriteExtra::create( - modSprite, - this, - menu_selector(NewProfilePage::onBadgePressed) - ); - } - - badgeBtn->setID("mod-badge"); - badgeBtn->setUserObject(CCInteger::create(comment->m_modBadge)); - if (cell->getChildByIDRecursive("percentage-label")) { - username_menu->insertBefore(badgeBtn, cell->getChildByIDRecursive("percentage-label")); - } else { - username_menu->addChild(badgeBtn); - } - } - - if (username_menu != nullptr) username_menu->updateLayout(); - - const std::function then = [this, cell](std::string const& result) { - badgeHandle(result, cell, cell->m_comment->m_commentID); - }; - - if (!badgesDataComments.empty()) { - then(badgesDataComments); - return; - } - - m_fields->m_listener.bind([then = std::move(then)] (web::WebTask::Event* e) { - if (web::WebResponse* res = e->getValue()) { - if (res->ok()) { - badgesDataComments = res->string().unwrapOrDefault(); - then(badgesDataComments); - } - } - }); - - auto req = web::WebRequest(); - m_fields->m_listener.setFilter(req.get("https://clarifygdps.com/gdutils/gdutils_roles.php?version=1.0")); - } -}; diff --git a/src/Styles/NewGJCommentList.h b/src/Styles/NewGJCommentList.h deleted file mode 100644 index 422186b..0000000 --- a/src/Styles/NewGJCommentList.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -#include "../includes.h" -#include - -using namespace geode::prelude; \ No newline at end of file diff --git a/src/Styles/NewProfilePage.cpp b/src/Styles/NewProfilePage.cpp deleted file mode 100644 index c3d9087..0000000 --- a/src/Styles/NewProfilePage.cpp +++ /dev/null @@ -1,344 +0,0 @@ -#include "NewProfilePage.h" -#include "../includes.h" -#include "Geode/utils/general.hpp" -#include -#include - -std::string badgesDataProfile = ""; - -void NewProfilePage::onBadgePressed(CCObject* pSender) { - geode::log::info("Object: {}", static_cast(pSender)->getUserObject()); - CCInteger* score = static_cast(static_cast(pSender)->getUserObject()); - geode::log::info("Badge pressed: {}", score->getValue()); - switch (score->getValue()) { - case 1: - #ifndef GEODE_IS_ANDROID - FLAlertLayer::create( - nullptr, - "Geometry Dash Moderator", - R"text( - A Geometry Dash Moderator is a user that has been chosen by RobTop and other Moderators on the team by suggestions. - - Their first task is to suggest levels to be rated to RobTop, the current developer of the game and the maintainer of the level rating system, he is the only one that can rate levels. - - How to become a Geometry Dash Moderator? - - Many community members want to become a Moderator to be able to suggest levels for a rating. Similar to rating, Moderator promotions are solely done by RobTop himself on a case-by-case basis, so there are no clear steps to getting it. Here are some general criteria: - - Be nice. - - Be active in the community. - - Be trustworthy. - - Be able to judge levels well. - - If you display these qualities over time, there is a chance that other Moderators may suggest you to RobTop. Of course, showing that you are qualified may be difficult if you do not share circles with pre-existing Moderators. If you are interested, you can apply to join the team using our application form. Make sure you read the information in it clearly before submitting. Here is the link: - - https://forms.gle/XyRGtFzD3hshDUQV7 - )text", - "OK", - nullptr, - 400.0f, - true, - 100.0f, - 1.0f - )->show(); - #else - FLAlertLayer::create( - nullptr, - "Geometry Dash Moderator", - R"text( - A Geometry Dash Moderator is a user that has been chosen by RobTop and other Moderators on the team by suggestions. - - Their first task is to suggest levels to be rated to RobTop, the current developer of the game and the maintainer of the level rating system, he is the only one that can rate levels. - )text", - "OK", - nullptr, - 400.0f, - true, - 100.0f, - 1.0f - )->show(); - - #endif - break; - case 2: - #ifndef GEODE_IS_ANDROID // android height broken - FLAlertLayer::create( - nullptr, - "Geometry Dash Elder Moderator", - R"text( - A Geometry Dash Elder Moderator is a user that has been chosen by RobTop and other Moderators on the team by suggestions and was already a Geometry Dash Moderator before his promotion. They are the pillars of the moderation team. - - Their first task is to suggest levels to be rated to RobTop, the current developer of the game and the maintainer of the level rating system, which he is the only one that can rate levels. But they also have the power to moderate comments, whitelists Newgrounds artists and unlocks updates for old rated levels. - - How to become a Geometry Dash Moderator? - - Many community members want to become a Moderator to be able to suggest levels for a rating. Similar to rating, Moderator promotions are solely done by RobTop himself on a case-by-case basis, so there are no clear steps to getting it. Here are some general criteria: - - Be nice. - - Be active in the community. - - Be trustworthy. - - Be able to judge levels well. - - If you display these qualities over time, there is a chance that other Moderators may suggest you to RobTop. Of course, showing that you are qualified may be difficult if you do not share circles with pre-existing Moderators. If you are interested, you can apply to join the team using our application form. Make sure you read the information in it clearly before submitting. Here is the link: - - https://forms.gle/XyRGtFzD3hshDUQV7 - )text", - "OK", - nullptr, - 400.0f, - true, - 100.0f, - 1.0f - )->show(); - #else - FLAlertLayer::create( - nullptr, - "Geometry Dash Elder Moderator", - R"text( - A Geometry Dash Elder Moderator is a user that has been chosen by RobTop and other Moderators on the team by suggestions and was already a Geometry Dash Moderator before his promotion. They are the pillars of the moderation team. - - Their first task is to suggest levels to be rated to RobTop, the current developer of the game and the maintainer of the level rating system, which he is the only one that can rate levels. But they also have the power to moderate comments, whitelists Newgrounds artists and unlocks updates for old rated levels. - )text", - "OK", - nullptr, - 400.0f, - true, - 100.0f, - 1.0f - )->show(); - #endif - break; - case 3: - FLAlertLayer::create( - nullptr, - "Geometry Dash Leaderboard Moderator", - R"text( -A Geometry Dash Leaderboard Moderator is a user that has been chosen by RobTop and other Leaderboard Moderators on the team by suggestions. - -Their first task is to moderate the Top 100 / Global leaderboard (as well as level-specific ones) and ban cheaters to keep the leaderboards clean. - -How to become a Geometry Dash Leaderboard Moderator? - -If you are interested, you can apply to join the team using our application form. Make sure you read the information in it clearly before submitting. Here is the link: - -https://docs.google.com/forms/d/e/1FAIpQLSfrJyIVM7KzPyTgzGZ0CSuGBPv40160W9I6bPiMgLRawjJJBg/viewform - )text", - "OK", - nullptr, - 500.0f, - true, - 40.0f, - 1.0f - )->show(); - break; - } -} - -void NewProfilePage::onRobTopBadgePressed(CCObject* pSender) { - FLAlertLayer::create( - nullptr, - "RobTop Games", - R"text( -RobTop is the creator and the main developer of Geometry Dash. - -He is the only developer of the game and is responsible for all the updates and content that is added to the game. - )text", - "OK", - nullptr, - 300.0f - )->show(); -} - -void NewProfilePage::badgeFactoryAlert(CCObject* pSender) { - CCArray* children = static_cast(static_cast(pSender)->getUserObject()); - - std::string alertTitle = static_cast(children->objectAtIndex(0))->getCString(); - std::string alertDesc = static_cast(children->objectAtIndex(1))->getCString(); - float alertWidth = static_cast(children->objectAtIndex(2))->getValue(); - bool isKofi = strcmp(static_cast(children->objectAtIndex(3))->getCString(), "1") == 0; - - // Fix \n in alertDesc - std::string::size_type n = 0; - while ((n = alertDesc.find("\\n", n)) != std::string::npos) { - alertDesc.replace(n, 2, "\n"); - n += 1; - } - - if (isKofi) { - geode::createQuickPopup( - alertTitle.c_str(), - alertDesc.c_str(), - "OK", "Ko-Fi", - [](auto, bool btn2) { - if (btn2) { - geode::utils::web::openLinkInBrowser("https://ko-fi.com/gdutils"); - } - }, - alertWidth - ); - } else { - FLAlertLayer::create( - nullptr, - alertTitle.c_str(), - alertDesc.c_str(), - "OK", - nullptr, - alertWidth - )->show(); - } -} - -// Mod badges descriptions & GDUtils dev badge -class $modify(ProfilePage) { - struct Fields { - EventListener m_listener; - }; - - void requestGDUtilsBadges(int accountID, CCLayer* layer) { - const std::function then = [this, accountID, layer](std::string const& result) { - badgesDataProfile = result; - - std::vector data_user = MoreLeaderboards::getWords(result, "|"); - - while (data_user.size() > 0) { - std::vector data = MoreLeaderboards::getWords(data_user[0], "?"); - - int badge = 0; - int accountID_data = 0; - std::string badge_id = ""; - std::string badge_sprite = ""; - float badge_scale = 1.0f; - std::string alertTitle = ""; - std::string alertDesc = ""; - float alertWidth = 300.0f; - bool isKofi = false; - - while (data.size() > 0) { - std::string id = data[0]; - std::string name = data[1]; - - if (id == "1") { - accountID_data = numFromString(name).unwrapOrDefault(); - } else if (id == "3") { - badge = numFromString(name).unwrapOrDefault(); - } else if (id == "4") { - badge_sprite = name; - } else if (id == "5") { - badge_id = name; - } else if (id == "6") { - badge_scale = numFromString(name).unwrapOrDefault(); - } else if (id == "8") { - alertTitle = name; - } else if (id == "9") { - alertDesc = name; - } else if (id == "10") { - alertWidth = numFromString(name).unwrapOrDefault(); - } else if (id == "11") { - isKofi = name == "1"; - } - - data.erase(data.begin()); - data.erase(data.begin()); - } - - if (accountID_data == accountID) { - if (!layer->getChildByIDRecursive(badge_id)) { - CCMenu* username_menu = typeinfo_cast(layer->getChildByIDRecursive("username-menu")); - - auto badgeGDUtil = CCSprite::createWithSpriteFrameName(fmt::format("{}"_spr, badge_sprite).c_str()); - badgeGDUtil->setScale(badge_scale); - - auto badgeGDUtilBtn = CCMenuItemSpriteExtra::create( - badgeGDUtil, - layer, - menu_selector(NewProfilePage::badgeFactoryAlert) - ); - - badgeGDUtilBtn->setID(badge_id); - - auto array = CCArray::create(); - array->addObject(CCString::create(alertTitle)); - array->addObject(CCString::create(alertDesc)); - array->addObject(CCFloat::create(alertWidth)); - array->addObject(CCString::create(isKofi ? "1" : "0")); - badgeGDUtilBtn->setUserObject(array); - - username_menu->addChild(badgeGDUtilBtn); - username_menu->updateLayout(); - } - } - - data_user.erase(data_user.begin()); - } - }; - const std::function expect = [this](std::string const& error) { - log::error("Failed to get GDUtils badges: {}", error); - }; - - // If we already have the badges data, don't request it again - if (badgesDataProfile != "") { - then(badgesDataProfile); - return; - } - - // Request the badges data - m_fields->m_listener.bind([expect = std::move(expect), then = std::move(then)] (web::WebTask::Event* e) { - if (web::WebResponse* res = e->getValue()) { - if (res->ok()) { - then(res->string().unwrapOrDefault()); - } else { - expect("Request failed"); - } - } - }); - - auto req = web::WebRequest(); - m_fields->m_listener.setFilter(req.get("https://clarifygdps.com/gdutils/gdutils_roles.php?version=1.0")); - } - - void loadPageFromUserInfo(GJUserScore* a2) { - ProfilePage::loadPageFromUserInfo(a2); - auto layer = m_mainLayer; - CCMenuItemSpriteExtra* badgeBtn = nullptr; - - CCMenu* username_menu = typeinfo_cast(layer->getChildByIDRecursive("username-menu")); - CCLabelBMFont* label = typeinfo_cast(layer->getChildByIDRecursive("username-label")); - - if (layer) { - CCSprite* modbadge = typeinfo_cast(layer->getChildByIDRecursive("mod-badge")); - if (modbadge != nullptr) { - modbadge->removeFromParentAndCleanup(true); - - if (a2->m_userName == "RobTop" && Mod::get()->template getSettingValue("customBadges")) { - auto robtopSpr = CCSprite::createWithSpriteFrameName("robtop_badge.png"_spr); - badgeBtn = CCMenuItemSpriteExtra::create( - robtopSpr, - this, - menu_selector(NewProfilePage::onRobTopBadgePressed) - ); - } else { - CCSprite* modSprite; - if (a2->m_modBadge == 1) { - modSprite = CCSprite::createWithSpriteFrameName("modBadge_01_001.png"); - } else if (a2->m_modBadge == 2) { - modSprite = CCSprite::createWithSpriteFrameName("modBadge_02_001.png"); - } else if (a2->m_modBadge == 3) { - modSprite = CCSprite::createWithSpriteFrameName("modBadge_03_001.png"); - } - - badgeBtn = CCMenuItemSpriteExtra::create( - modSprite, - this, - menu_selector(NewProfilePage::onBadgePressed) - ); - } - - badgeBtn->setID("mod-badge"); - badgeBtn->setUserObject(CCInteger::create(a2->m_modBadge)); - username_menu->addChild(badgeBtn); - } - - if (username_menu != nullptr) username_menu->updateLayout(); - } - - if (Mod::get()->template getSettingValue("customBadges")) requestGDUtilsBadges(a2->m_accountID, layer); - } -}; diff --git a/src/Styles/NewProfilePage.h b/src/Styles/NewProfilePage.h deleted file mode 100644 index 0b43953..0000000 --- a/src/Styles/NewProfilePage.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include -#include -#include "../MoreLeaderboards/MoreLeaderboards.h" - -using namespace geode::prelude; - -class NewProfilePage : public CCLayer { - public: - void onBadgePressed(CCObject* pSender); - void onRobTopBadgePressed(CCObject* pSender); - void badgeFactoryAlert(CCObject* pSender); -}; diff --git a/src/Styles/TheVault.cpp b/src/Styles/TheVault.cpp deleted file mode 100644 index 2619a8b..0000000 --- a/src/Styles/TheVault.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "../includes.h" -#include - -class $modify(SecretLayer) { - bool init() { - if (!SecretLayer::init()) return false; - - if (!Mod::get()->template getSettingValue("secretLayerDesign")) return true; - - auto winSize = CCDirector::sharedDirector()->getWinSize(); - auto bg = CCSprite::createWithSpriteFrameName("thevault.png"_spr); - - bg->setPosition(winSize / 2); - bg->setZOrder(-1); - bg->setScaleY(winSize.height / bg->getContentSize().height); - bg->setScaleX(winSize.width / bg->getContentSize().width); - this->addChild(bg); - - // Get vault name - auto vaultName = this->getChildByID("vault-name"); - if (vaultName) { - vaultName->setVisible(false); - } - - return true; - } -}; diff --git a/src/Utils/DemonList.cpp b/src/Utils/DemonList.cpp deleted file mode 100644 index 97c8e1a..0000000 --- a/src/Utils/DemonList.cpp +++ /dev/null @@ -1,205 +0,0 @@ -#include "../includes.h" -#include -#include -#include -#include "../Settings/CustomSettings.hpp" - - -// demon list -std::unordered_map demonListCache; // Will clear after game exit, or if user deletes level -static std::unordered_map RUNNING_REQUESTS {}; -static std::mutex lock_var; - -// love url encoded characters :D -// also for some reason this is required on mac because Geode's web requests doesnt automatically append this for some reason. -// SURELY THIS WONT AFFECT LEVELS WITH SOME OTHER BREAKING SYMBOLS. -std::string url_encode(const std::string& value) { - std::string encoded; - encoded.reserve(value.size()); - for (char c : value) { - if (c == ' ') { - encoded += "%20"; - } else { - encoded += c; - } - } - return encoded; -} - -class $modify(LevelInfoLayer) { - // chat jippity - void set(int key, int value) { - demonListCache[key] = value; - } - - // Function to check if a key exists in the cache. - bool exists(int key) { - return demonListCache.find(key) != demonListCache.end(); - } - - // Function to get a value from the cache. - int get(int key) { - auto it = demonListCache.find(key); - if (it != demonListCache.end()) { - return it->second; - } - // Return -1 or some other default value to indicate the key wasn't found. - return -1; - } - - bool remove(int key) { - return demonListCache.erase(key) == 1; - } - float getScaleBasedPos(int pos) { - if (pos > 0 && pos < 10) return 0.5F; - if (pos > 10 && pos < 100) return 0.4F; - if (pos > 100 && pos < 1000) return 0.3F; - if (pos > 1000 && pos < 10000) return 0.2F; - return 0.1F; - } - bool init(GJGameLevel* level, bool p1) { // inspiration le gdbrowser, what does p1 do? idk - if (!LevelInfoLayer::init(level, p1)) return false; - if (!Mod::get()->template getSettingValue("demonListPlacement")) return true; - - if (level->m_demon.value() == 0 || level->m_stars.value() != 10) return true; - if (level->m_demonDifficulty != 6) return true; - - auto director = CCDirector::sharedDirector(); - auto winSize = director->getWinSize(); - auto demonSpr = CCSprite::createWithSpriteFrameName("diffIcon_06_btn_001.png"); - demonSpr->setPosition({(winSize.width / 2) - 85, (winSize.height / 2) + 18}); - demonSpr->setScale(0.5F); - demonSpr->setID("demon-spr"_spr); - auto positionLabel = CCLabelBMFont::create("N/A", "bigFont.fnt"); - positionLabel->setPosition({(winSize.width / 2) - 107, (winSize.height / 2) + 18}); // 178 - positionLabel->setScale(0.5F); - positionLabel->setVisible(false); - positionLabel->setID("demon-pos"_spr); - demonSpr->setVisible(false); - this->addChild(demonSpr); - this->addChild(positionLabel); - if (level->m_coins > 0) { - positionLabel->setPositionY(positionLabel->getPositionY() - 18); - demonSpr->setPositionY(demonSpr->getPositionY() - 18); - } - int levelID = level->m_levelID.value(); - if (exists(levelID)) { - int position = get(levelID); - if (position > 0) { - positionLabel->setString(fmt::format("#{}", position).c_str()); - positionLabel->setScale(getScaleBasedPos(position)); - positionLabel->setVisible(true); - demonSpr->setVisible(true); - } - } else { - this->retain(); - auto loading_circle = LoadingCircle::create(); - if (level->m_coins > 0) { - loading_circle->setPosition({-100, -2}); - loading_circle->setScale(0.3F); - } else { - loading_circle->setPosition({-100, 8}); - loading_circle->setScale(0.4F); - } - loading_circle->setParentLayer(this); - loading_circle->show(); - - const std::function)> then = [this, level, levelID, loading_circle, positionLabel, demonSpr, winSize](Result const& result_json) { - matjson::Value json = result_json.unwrapOrDefault(); - - std::string listId = Mod::get()->template getSettingValue("demonListSelection"); - - if (listId == "Pointercrate") { - if (loading_circle != nullptr) { - loading_circle->fadeAndRemove(); - } - auto scene = CCDirector::sharedDirector()->getRunningScene(); - if (json.dump() == "[]") { //idk how to check size, doing .count crashes - log::info("Level not found in Pointercrate."); - this->release(); - } else { - auto info = json.get(0); - if (info.isOk()) { - auto positionRes = info.unwrap().get("position"); - if (positionRes.isOk()) { - int position = positionRes.unwrap().asInt().unwrapOrDefault(); - positionLabel->setString(fmt::format("#{}", position).c_str()); - positionLabel->setScale(getScaleBasedPos(position)); - positionLabel->setVisible(true); - demonSpr->setVisible(true); - set(levelID, position); - log::info("Level found in Pointercrate! {} at #{}", level->m_levelName.c_str(), position); - } - } - this->release(); - - } - } else { - if (loading_circle != nullptr) { - loading_circle->fadeAndRemove(); - } - auto scene = CCDirector::sharedDirector()->getRunningScene(); - if (json.contains("code")) { - this->release(); - } else { - auto positionRes = json.get("position"); - if (positionRes.isOk()) { - int position = positionRes.unwrap().asInt().unwrapOrDefault(); - positionLabel->setString(fmt::format("#{}", position).c_str()); - positionLabel->setScale(getScaleBasedPos(position)); - positionLabel->setVisible(true); - demonSpr->setVisible(true); - set(levelID, position); - log::info("Level found in AREDL! {} at #{}", level->m_levelName.c_str(), position); - } - this->release(); - } - } - }; - const std::function expect = [this, loading_circle](std::string const& error) { - if (loading_circle != nullptr) { - loading_circle->fadeAndRemove(); - } - log::error("Error while sending a request to Demon List: {}", error); - /*FLAlertLayer::create(nullptr, - "Error", - "Failed to make a request to Demon List. Please either try again later, look at the error logs to see what might have happened, or report this to the developers.", - "OK", - nullptr, - 350.0F - )->show();*/ - this->release(); - }; - - std::string listId = Mod::get()->template getSettingValue("demonListSelection"); - std::string url = ""; - if (listId == "Pointercrate") { - url = fmt::format("https://pointercrate.com/api/v2/demons/listed/?level_id={}", levelID); - } else { - url = fmt::format("https://api.aredl.net/api/aredl/levels/{}", levelID); - } - - geode::utils::web::WebRequest request = web::WebRequest(); - const std::lock_guard lock(lock_var); - RUNNING_REQUESTS.emplace( - "@loaderDemonListLevelInfo", - request.get(url.c_str()).map( - [expect = std::move(expect), then = std::move(then)](web::WebResponse* response) { - const std::lock_guard lock(lock_var); - if (response->ok()) { - then(response->json()); - } else { - expect("Request failed"); - } - - RUNNING_REQUESTS.erase("@loaderDemonListLevelInfo"); - return *response; - } - ) - ); - } - - return true; - } -}; -// demon list diff --git a/src/Utils/DownloadManager.cpp b/src/Utils/DownloadManager.cpp deleted file mode 100644 index 9519ddd..0000000 --- a/src/Utils/DownloadManager.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include "DownloadManager.h" -#ifndef GEODE_IS_MACOS // unfortunately figs video player not supported on mac becuase opengl32 doesnt want to compile correctly koeirjnfioewbnfejwf -#include "../ProcessLambdas.h" -#include -#include -#include - -EventListener m_listener_dl; - -// ------ -// 204 = MAX -// 0 = MIN -bool ProgressBar::init() { // on purpose im not even providing any params because why would we!?; - progressBar->setPosition({3, 8}); - progressBar->setAnchorPoint({ 0, 0.5 }); - progressBar->setTextureRect(CCRect(0, 0, 204, 8)); - ccTexParams params = { GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT }; // tf is this nonsense mat - progressBar->getTexture()->setTexParameters(¶ms); - this->addChild(outerBg); - progressBar->setZOrder(-1); - outerBg->addChild(progressBar); - return true; -} - -void ProgressBar::setProgress(float percentage) { - this->m_pPercentage = percentage; - float realPercentage = (204/100) * this->m_pPercentage; // "Result of integer division used in a floating point" ok i know clangd warnings wow - progressBar->setTextureRect(CCRect(0, 0, realPercentage, 8)); -} - -ProgressBar* ProgressBar::create() { - auto pRet = new ProgressBar(); - - if (pRet && pRet->init()) { - pRet->autorelease(); - return pRet; - } - - CC_SAFE_DELETE(pRet); - return nullptr; -} -// ------ -// credits https://stackoverflow.com/a/1639047 -int DownloadManager::progress_func(void*, double totalDownload, std::optional downloadAmount, double TotalToUpload, double NowUploaded) { - if (totalDownload <= 0.0 || !downloadAmount) return 0; - float amountDownloaded = round((downloadAmount.value() / totalDownload) * 100); - auto scene = CCDirector::sharedDirector()->getRunningScene(); - if (m_progressBar != nullptr) { - m_progressBar->setProgress(amountDownloaded); - } - return 0; -} - -bool DownloadManager::setup(const char* url, const char* destination, cocos2d::SEL_MenuHandler selector) { - auto title = CCLabelBMFont::create("Downloading...", "bigFont.fnt"); - title->setScale(0.8f); - m_mainLayer->addChildAtPosition(title, Anchor::Top, {0, -25}); - - auto winSize = cocos2d::CCDirector::sharedDirector()->getWinSize(); - loading_circle->setParentLayer(this); - loading_circle->setScale(0.675f); - loading_circle->show(); - m_progressBar = ProgressBar::create(); - m_progressBar->setProgress(0.0F); - m_mainLayer->addChildAtPosition(m_progressBar, Anchor::Center, {0, -30}); - - auto text = cocos2d::CCLabelBMFont::create("Do not close this menu while the file is being downloaded.", "chatFont.fnt"); - text->setAlignment(cocos2d::kCCTextAlignmentCenter); - text->setScale(.5F); - m_mainLayer->addChildAtPosition(text, Anchor::Bottom, {0, 18}); - - // def not copied from geode hahahaha - const std::function then = [this, destination, selector](geode::ByteVector const& data) { - // Save the file - (void)geode::utils::file::writeBinary(destination, data); - - ProcessLambdas::callMenuHandler(this, selector); - this->onClose(nullptr); - }; - const std::function expect = [this](int const& error) { - FLAlertLayer::create(nullptr, "Error!", "An error occured while trying to send a request to the servers. Check logs for more information.", "OK", nullptr, 200.0F)->show(); - log::error("Error downloading: {}", error); - }; - - geode::utils::web::WebRequest request = web::WebRequest(); - m_listener_dl.bind([this, expect = std::move(expect), then = std::move(then)] (web::WebTask::Event* e) { - if (web::WebProgress* progress = e->getProgress()) { - progress_func(NULL, 100, progress->downloadProgress(), progress->uploadTotal(), progress->uploaded()); - } else if (web::WebResponse* result = e->getValue()) { - if (result->ok()) { - then(result->data()); - } else { - expect(result->code()); - } - } - }); - - m_listener_dl.setFilter(request.get(url)); - return true; -} - -DownloadManager* DownloadManager::create(const char* url, const char* destination, cocos2d::SEL_MenuHandler selector) { - auto ret = new DownloadManager(); - if (ret->initAnchored(300.f, 150.f, url, destination, selector)) { - ret->autorelease(); - return ret; - } - delete ret; - return nullptr; -} -// below is copied from the gdr mod lol -#endif diff --git a/src/Utils/DownloadManager.h b/src/Utils/DownloadManager.h deleted file mode 100644 index 425d73d..0000000 --- a/src/Utils/DownloadManager.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once -// windows only because i cant get this to work, actually im too lazy -#ifndef GEODE_IS_MACOS -#include -using namespace geode::prelude; -class ProgressBar : public CCNode { - protected: - float m_pPercentage = 0; - CCSprite* outerBg = CCSprite::create("slidergroove.png"); - CCSprite* progressBar = CCSprite::create("sliderBar.png"); - bool init(); - public: - void testProgressbar(); - virtual void setProgress(float percentage); - static ProgressBar* create(); -}; -class DownloadManager : public geode::Popup { - LoadingCircle* loading_circle = LoadingCircle::create(); - protected: - bool setup(const char* url, const char* destination, cocos2d::SEL_MenuHandler selector); - ProgressBar* m_progressBar; - public: - static constexpr const float s_defWidth = 300.0f; - static constexpr const float s_defHeight = 180.0f; - static DownloadManager* create(const char* url, const char* destination, cocos2d::SEL_MenuHandler callback); //, cocos2d::SEL_MenuHandler callback - - // Downloader class - int progress_func(void*, double, std::optional, double, double); -}; -#endif diff --git a/src/Utils/FriendsProfilePage.cpp b/src/Utils/FriendsProfilePage.cpp deleted file mode 100644 index ccf9fbd..0000000 --- a/src/Utils/FriendsProfilePage.cpp +++ /dev/null @@ -1,216 +0,0 @@ -#include "../includes.h" -#include -// Utils - -// Function to convert a const char* to lowercase -const char* toLowerCase(const char* str) { - char* result = new char[strlen(str) + 1]; - size_t i = 0; - - while (str[i]) { - result[i] = std::tolower(str[i]); - i++; - } - - result[i] = '\0'; - return result; -} - -class SearchUserLayer : public Popup<> { - protected: - bool setup() { - input_username->setMaxCharCount(20); - input_username->setPlaceholder(""); - input_username->setPositionY(10); - - m_buttonMenu->addChildAtPosition(input_username, Anchor::Center); - auto winSize = cocos2d::CCDirector::sharedDirector()->getWinSize(); - auto validate_spr = ButtonSprite::create("Search", 60, true, "bigFont.fnt", "GJ_button_01.png", 30, .5F); - auto validate_btn = CCMenuItemSpriteExtra::create( - validate_spr, - this, - menu_selector(SearchUserLayer::onValidate) - ); - m_buttonMenu->addChildAtPosition(validate_btn, Anchor::Center, {0, -35}); - return true; - } - void onValidate(cocos2d::CCObject*); - public: - TextInput* input_username = TextInput::create(200.0F, "Username", "bigFont.fnt"); - static SearchUserLayer* create() { - auto ret = new SearchUserLayer(); - if (ret->initAnchored(260.f, 60.f)) { - ret->autorelease(); - return ret; - } - delete ret; - return nullptr; - } -}; - -class $modify(FriendPage, FriendsProfilePage) { - bool init(UserListType type) { - // If the base init fails, stop here - if (!FriendsProfilePage::init(type)) return false; - // If the setting is disabled, stop here - if (!Mod::get()->template getSettingValue("friendSearch")) return true; - - auto menu = this->m_buttonMenu; - - auto searchSpr = CCSprite::createWithSpriteFrameName("gj_findBtn_001.png"); - searchSpr->setScale(1.225F); - auto searchBtn = CCMenuItemSpriteExtra::create( - searchSpr, - this, - menu_selector(FriendPage::onSearch) - ); - searchBtn->setPosition(320, 0); - menu->addChild(searchBtn); - return true; - } - - void onSearch(CCObject*) { - SearchUserLayer::create()->show(); - } - - static TableView* getCustomList(CCArray* sceneChildren) { - CCLayer* test1 = typeinfo_cast(misc::findNode("FriendsProfilePage")); - if (test1 == nullptr) { - // safeguard from crashing - FLAlertLayer::create(nullptr, - "Error", - "The mod could not find the FriendsProfilePage layer. Please either try again later, removing mods that may be interfering with the scene, or report this to the developers.", - "OK", - nullptr, - 350.0F - )->show(); - return nullptr; - } - test1 = typeinfo_cast(test1->getChildren()->objectAtIndex(0)); - CCLayer* test2 = nullptr; - for (int i = 0; i < test1->getChildrenCount(); i++) { - if (misc::getNodeName(test1->getChildren()->objectAtIndex(i)) == "GJCommentListLayer") { - test2 = static_cast(test1->getChildren()->objectAtIndex(i)); - break; - } - } - - // If we couldn't find the comment list layer, return - if (test2 == nullptr) { - // safeguard from crashing - FLAlertLayer::create(nullptr, - "Error", - "The mod could not find the GJCommentListLayer layer. Please either try again later, removing mods that may be interfering with the scene, or report this to the developers.", - "OK", - nullptr, - 350.0F - )->show(); - return nullptr; - } - - auto test3 = static_cast(test2->getChildren()->objectAtIndex(0)); - - // If you don't have friend, show alert (sorry for you) - if (test3->getChildrenCount() <= 0) { - // another safeguard - FLAlertLayer::create(nullptr, - "Error", - "You have no friends!", - "OK", - nullptr, - 200.0F - )->show(); - return nullptr; - } - - return static_cast(test3->getChildren()->objectAtIndex(0)); - } - - static void searchUser(const char* username) { - auto scene = CCDirector::sharedDirector()->getRunningScene(); - auto sceneChildren = scene->getChildren(); - auto customList = getCustomList(sceneChildren); - - // If the list is null, return - if (customList == nullptr) return; - - CCContentLayer* contentLayer = static_cast( - customList->getChildren()->objectAtIndex(0) - ); - - int counter_page = 0; - bool found = false; - - // Iterate through all cells in the list - for (int i = 0; i < contentLayer->getChildrenCount(); i++) { - GJUserCell* cell = static_cast( - contentLayer->getChildren()->objectAtIndex(i) - ); - - const char* str1 = cell->m_userScore->m_userName.c_str(); - - // If username is found in the cell's username (case insensitive) - if (strstr(toLowerCase(str1), toLowerCase(username)) != nullptr) { - customList->scrollLayer(-9999999); - customList->scrollLayer(counter_page); - - found = true; - - // Pulse only one time cell color animation - auto originalColor = cell->getChildByType(0)->getColor(); - auto tintTo1 = CCTintTo::create(0.2f, 0, 255, 0); // Change to green - auto tintTo2 = CCTintTo::create(0.5f, originalColor.r, originalColor.g, originalColor.b); // Change back to original color - auto sequence = CCSequence::create(tintTo1, tintTo2, nullptr); - cell->getChildByType(0)->runAction(sequence); - - break; - } - counter_page += 45; - } - - // If user not found, show alert - if (!found) { - std::string str = username; - FLAlertLayer::create(nullptr, - "Error", - "User not found : " + str, - "OK", - nullptr, - 200.0F - )->show(); - } - } - - void setupUsersBrowser(cocos2d::CCArray * users, UserListType type) - { - FriendsProfilePage::setupUsersBrowser(users, type); - - if (m_buttonMenu->getChildByID("friendsScrollBar")) - { - m_buttonMenu->removeChildByID("friendsScrollBar"); - } - } - - virtual void getUserListFinished(cocos2d::CCArray* a1, UserListType a2) { - FriendsProfilePage::getUserListFinished(a1,a2); - - auto menu = this->m_buttonMenu; - - // Add custom scrollbar - auto scrollBar = Scrollbar::create(this->m_listLayer->m_list->m_tableView); - scrollBar->setPosition(390, -140); - scrollBar->setID("friendsScrollBar"); - menu->addChild(scrollBar); - } - - virtual void onUpdate(UserListType a1) { - FriendsProfilePage::forceReloadList(a1); - - m_buttonMenu->removeChildByID("friendsScrollBar"); - } -}; - -void SearchUserLayer::onValidate(CCObject* pSender) { - FriendPage::searchUser(input_username->getString().c_str()); - Popup::onClose(pSender); -} diff --git a/src/Utils/InfoNewLayer.cpp b/src/Utils/InfoNewLayer.cpp deleted file mode 100644 index ef33337..0000000 --- a/src/Utils/InfoNewLayer.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "InfoNewLayer.h" -#include - -void InfoNewLayer::onCopyLevelURL(CCObject* pSender) { - std::string level = static_cast(static_cast(pSender)->getUserObject())->getCString(); - utils::clipboard::write("https://gdutils.com/" + level); - - auto notification = Notification::create("Copied level URL to clipboard!", NotificationIcon::Success); - notification->setZOrder(1000); - notification->setTime(0.2f); - notification->show(); -} - -// Copy button for sharing levels -class $modify(InfoLayer) { - bool init(GJGameLevel* level, GJUserScore* userscore, GJLevelList* levellist) { - if (!InfoLayer::init(level, userscore, levellist)) return false; - - // Check if it's InfoLayer for level - if (level == nullptr) return true; - if (!Mod::get()->template getSettingValue("levelsProtocolButton")) return true; - - std::string levelID = std::to_string(level->m_levelID.value()); - - CCMenu* menu = typeinfo_cast(this->getChildByIDRecursive("left-side-menu")); - auto copySpr = CCSprite::createWithSpriteFrameName("GJ_redoBtn_001.png"); - copySpr->setScale(.7f); - auto copyBtn = CCMenuItemSpriteExtra::create( - copySpr, - this, - menu_selector(InfoNewLayer::onCopyLevelURL) - ); - copyBtn->setUserObject(cocos2d::CCString::create(gd::string(levelID))); - copyBtn->setPosition(14, -55); - menu->addChild(copyBtn); - - return true; - } -}; diff --git a/src/Utils/InfoNewLayer.h b/src/Utils/InfoNewLayer.h deleted file mode 100644 index 1ec5b49..0000000 --- a/src/Utils/InfoNewLayer.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include -#include -using namespace geode::prelude; - -class InfoNewLayer : public CCLayer { - public: - void onCopyLevelURL(CCObject* pSender); -}; diff --git a/src/Utils/ParticleManager.hpp b/src/Utils/ParticleManager.hpp deleted file mode 100644 index 04c400a..0000000 --- a/src/Utils/ParticleManager.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once -#include - -using namespace geode::prelude; - -// Code took from ItzKiba/BetterProgression, thanks! - -inline static CCParticleSystem* createParticles(int numParticles, ccColor3B startColor, ccColor3B endColor, std::string emitterType, std::string duration, std::string particleLifespan, std::string particleLifespanVariance, std::string angle, std::string angleVariance, std::string sourcePositionx, std::string sourcePositiony, std::string sourcePositionVariancex, std::string sourcePositionVariancey, std::string maxRadius, std::string minRadius, std::string startParticleSize, std::string finishParticleSize, std::string startParticleSizeVariance, std::string speed, std::string speedVariance, std::string gravityx, std::string gravityy, std::string startColorAlpha, std::string startColorVarianceRed, std::string startColorVarianceBlue, std::string startColorVarianceGreen, std::string startColorVarianceAlpha, std::string finishColorAlpha, std::string finishColorVarianceRed, std::string finishColorVarianceBlue, std::string finishColorVarianceGreen, std::string finishColorVarianceAlpha, std::string rotatePerSecond, std::string rotatePerSecondVariance, std::string rotationEndVariance, std::string textureFileName) { - auto dict = CCDictionary::createWithContentsOfFileThreadSafe("dragEffect.plist"); - - dict->setObject(CCString::create(emitterType), "emitterType"); - dict->setObject(CCString::create(duration), "duration"); - dict->setObject(CCString::createWithFormat("%i", numParticles), "maxParticles"); - dict->setObject(CCString::create(particleLifespan), "particleLifespan"); - dict->setObject(CCString::create(particleLifespanVariance), "particleLifespanVariance"); - dict->setObject(CCString::create(angle), "angle"); - dict->setObject(CCString::create(angleVariance), "angleVariance"); - dict->setObject(CCString::create(sourcePositionx), "sourcePositionx"); - dict->setObject(CCString::create(sourcePositiony), "sourcePositiony"); - dict->setObject(CCString::create(sourcePositionVariancex), "sourcePositionVariancex"); - dict->setObject(CCString::create(sourcePositionVariancey), "sourcePositionVariancey"); - dict->setObject(CCString::create(maxRadius), "maxRadius"); - dict->setObject(CCString::create(minRadius), "minRadius"); - dict->setObject(CCString::create(startParticleSize), "startParticleSize"); - dict->setObject(CCString::create(finishParticleSize), "finishParticleSize"); - dict->setObject(CCString::create(startParticleSizeVariance), "startParticleSizeVariance"); - dict->setObject(CCString::create(speed), "speed"); - dict->setObject(CCString::create(speedVariance), "speedVariance"); - dict->setObject(CCString::create(gravityx), "gravityx"); - dict->setObject(CCString::create(gravityy), "gravityy"); - dict->setObject(CCString::create(fmt::format("{}", startColor.r)), "startColorRed"); - dict->setObject(CCString::create(fmt::format("{}", startColor.g)), "startColorGreen"); - dict->setObject(CCString::create(fmt::format("{}", startColor.b)), "startColorBlue"); - dict->setObject(CCString::create(startColorAlpha), "startColorAlpha"); - dict->setObject(CCString::create(startColorVarianceRed), "startColorVarianceRed"); - dict->setObject(CCString::create(startColorVarianceBlue), "startColorVarianceBlue"); - dict->setObject(CCString::create(startColorVarianceGreen), "startColorVarianceGreen"); - dict->setObject(CCString::create(startColorVarianceAlpha), "startColorVarianceAlpha"); - dict->setObject(CCString::create(fmt::format("{}", endColor.r)), "finishColorRed"); - dict->setObject(CCString::create(fmt::format("{}", endColor.g)), "finishColorGreen"); - dict->setObject(CCString::create(fmt::format("{}", endColor.b)), "finishColorBlue"); - dict->setObject(CCString::create(finishColorAlpha), "finishColorAlpha"); - dict->setObject(CCString::create(finishColorVarianceRed), "finishColorVarianceRed"); - dict->setObject(CCString::create(finishColorVarianceBlue), "finishColorVarianceBlue"); - dict->setObject(CCString::create(finishColorVarianceGreen), "finishColorVarianceGreen"); - dict->setObject(CCString::create(finishColorVarianceAlpha), "finishColorVarianceAlpha"); - dict->setObject(CCString::create(rotatePerSecond), "rotatePerSecond"); - dict->setObject(CCString::create(rotatePerSecondVariance), "rotatePerSecondVariance"); - dict->setObject(CCString::create(rotationEndVariance), "rotationEndVariance"); - dict->setObject(CCString::create(textureFileName), "textureFileName"); - - auto emitter = CCParticleSystemQuad::create(); - emitter->initWithDictionary(dict, false); - - return emitter; -} \ No newline at end of file diff --git a/src/config.hpp b/src/config.hpp new file mode 100644 index 0000000..83f2773 --- /dev/null +++ b/src/config.hpp @@ -0,0 +1,6 @@ +#pragma once +#define MAX_RECONNECT_ATTEMPTS 20 +#define AMQ_HOST "gdutils.clarifygdps.com" +#define AMQ_PORT 5672 +#define AMQ_USER "gd" +#define AMQ_PASS "GeometryDashisahorizontalrunnerstylegamedevelopedandpublishedbyRobTopGames" diff --git a/src/defs/geode.hpp b/src/defs/geode.hpp new file mode 100644 index 0000000..5d2802d --- /dev/null +++ b/src/defs/geode.hpp @@ -0,0 +1,5 @@ +#pragma once +#include +#include + +using namespace geode::prelude; diff --git a/src/defs/misc.hpp b/src/defs/misc.hpp new file mode 100644 index 0000000..2368b08 --- /dev/null +++ b/src/defs/misc.hpp @@ -0,0 +1,19 @@ +#pragma once +#include +#include +#include "geode.hpp" + +namespace misc { + template + std::vector> paginate(const std::vector& arr, size_t size) { + std::vector> paginated; + for (size_t i = 0; i < arr.size(); i += size) { + std::vector page; + for (size_t j = i; j < std::min(i + size, arr.size()); ++j) { + page.push_back(arr[j]); + } + paginated.push_back(page); + } + return paginated; + } +}; diff --git a/src/hooks/Backgrounds.cpp b/src/hooks/Backgrounds.cpp new file mode 100644 index 0000000..7f8c4fe --- /dev/null +++ b/src/hooks/Backgrounds.cpp @@ -0,0 +1,140 @@ +#include +#include +#include +// Backgrounds +// i dont like ios +#ifndef GEODE_IS_IOS +class $modify(UtilCCSprite, cocos2d::CCSprite) { + static CCSprite* create(char const* name) { + auto ret = CCSprite::create(name); + if (ret == nullptr) return ret; + // better code, thanks camila! + if (!strcmp(name, "GJ_gradientBG.png")) { + ret->retain(); + Loader::get()->queueInMainThread([=] { + if (ret != nullptr) { + if (ret->getColor() == ccc3(0, 102, 255)) { + auto scene = CCDirector::sharedDirector()->getRunningScene(); + if (scene->getChildrenCount() == 0) return; + auto layer = scene->getChildren()->objectAtIndex(0); + ret->setColor(Mod::get()->getSettingValue("background")); + } + ret->release(); + } + }); + } + return ret; + } +}; + +// Child background +class $modify(UtilCCScale9, cocos2d::extension::CCScale9Sprite) { + static cocos2d::extension::CCScale9Sprite* create(char const* name, CCRect rect) { + auto ret = cocos2d::extension::CCScale9Sprite::create(name, rect); + if (ret == nullptr) return ret; + // better code, thanks camila! + if ((!strcmp(name, "square02b_001.png") || !strcmp(name, "square02b_small.png"))) { + ret->retain(); + Loader::get()->queueInMainThread([=] { + if (ret != nullptr) { + // jouca waht + if (ret->getColor() == ccc3(0, 56, 141)) { + ccColor3B new_color = Mod::get()->getSettingValue("child-background"); + if (Mod::get()->getSettingValue("syncBGcolor")) { + new_color = Mod::get()->getSettingValue("background"); + } + if (Mod::get()->getSettingValue("addChildBDGradient")) { + new_color = ccc3(new_color.r * 0.79, new_color.g * 0.79, new_color.b * 0.79); + } + if (Mod::get()->getSettingValue("bgchild-transparency")) { + int opacity = Mod::get()->getSettingValue("bgchild-transparency-scroll"); + ret->setOpacity(opacity); + } + ret->setColor(new_color); + } else if (ret->getColor() == ccc3(0, 39, 98)) { + ccColor3B new_color = Mod::get()->getSettingValue("child-background"); + if (Mod::get()->getSettingValue("syncBGcolor")) { + new_color = Mod::get()->getSettingValue("background"); + } + if (Mod::get()->getSettingValue("addChildBDGradient")) { + new_color = ccc3(new_color.r * 0.71, new_color.g * 0.71, new_color.b * 0.71); + } + if (Mod::get()->getSettingValue("bgchild-transparency")) { + int opacity = Mod::get()->getSettingValue("bgchild-transparency-scroll"); + ret->setOpacity(opacity); + } + ret->setColor(new_color); + } else if (ret->getColor() == ccc3(0, 46, 117)) { + ccColor3B new_color = Mod::get()->getSettingValue("child-background"); + if (Mod::get()->getSettingValue("syncBGcolor")) { + new_color = Mod::get()->getSettingValue("background"); + } + if (Mod::get()->getSettingValue("addChildBDGradient")) { + new_color = ccc3(new_color.r * 0.74, new_color.g * 0.74, new_color.b * 0.74); + } + if (Mod::get()->getSettingValue("bgchild-transparency")) { + int opacity = Mod::get()->getSettingValue("bgchild-transparency-scroll"); + ret->setOpacity(opacity); + } + ret->setColor(new_color); + } else if (ret->getColor() == ccc3(0, 36, 91)) { + ccColor3B new_color = Mod::get()->getSettingValue("child-background"); + if (Mod::get()->getSettingValue("syncBGcolor")) { + new_color = Mod::get()->getSettingValue("background"); + } + if (Mod::get()->getSettingValue("addChildBDGradient")) { + new_color = ccc3(new_color.r * 0.70, new_color.g * 0.70, new_color.b * 0.70); + } + if (Mod::get()->getSettingValue("bgchild-transparency")) { + int opacity = Mod::get()->getSettingValue("bgchild-transparency-scroll"); + ret->setOpacity(opacity); + } + ret->setColor(new_color); + } else if (ret->getColor() == ccc3(0, 31, 79)) { + ccColor3B new_color = Mod::get()->getSettingValue("child-background"); + if (Mod::get()->getSettingValue("syncBGcolor")) { + new_color = Mod::get()->getSettingValue("background"); + } + if (Mod::get()->getSettingValue("addChildBDGradient")) { + new_color = ccc3(new_color.r * 0.67, new_color.g * 0.67, new_color.b * 0.67); + } + if (Mod::get()->getSettingValue("bgchild-transparency")) { + int opacity = Mod::get()->getSettingValue("bgchild-transparency-scroll"); + ret->setOpacity(opacity); + } + ret->setColor(new_color); + } + ret->release(); + } + }); + } + return ret; + } +}; + +static void toggleHook(bool value) { + for (auto& hook : geode::Mod::get()->getHooks()) { + if (hook->getDisplayName().starts_with("cocos2d::")) { + if (value) { + (void)hook->enable(); + } else { + (void)hook->disable(); + } + } + } +} + +$execute { + listenForSettingChanges("activate-background", [](bool value) { + log::info("Background changed to {}", value); + toggleHook(value); + }); +} + +$on_mod(Loaded) { + if (!Mod::get()->getSettingValue("activate-background")) { + toggleHook(false); + } +} + +#endif diff --git a/src/hooks/CustomBadges.cpp b/src/hooks/CustomBadges.cpp new file mode 100644 index 0000000..daeff83 --- /dev/null +++ b/src/hooks/CustomBadges.cpp @@ -0,0 +1,492 @@ +#include "Geode/utils/async.hpp" +#include "Geode/utils/string.hpp" +#include +#include +#include +#include + +std::string s_cachedBadgesResponse = ""; + +// Primary dispatch: unique int tag -> callback. +// Each call to makeBadgeButton gets a fresh tag stored directly on the button. +// Tags are never copied by BadgesAPI (its CCMenuItemSpriteExtra::create starts with kCCNodeTagInvalid = -1). +static int s_nextBadgeTag = 0; +static std::unordered_map> s_tagToCallback; + +// Fallback dispatch: CCSpriteFrame* -> tag, used when BadgesAPI copies our button. +// BadgesAPI does CCSprite::createWithSpriteFrame(originalFrame), so the new sprite +// shares the same CCSpriteFrame object and the lookup resolves to the last registered tag. +static std::unordered_map s_frameToTag; + +// Singleton target for all badge selectors. +// IMPORTANT: BadgesAPI copies our buttons as: +// CCMenuItemSpriteExtra::create(child->getNormalImage(), this/*BadgesAPI*/, child->m_pfnSelector) +// so `this` inside onBadgeClick may be the BadgesAPI object — NEVER dereference it. +// Only touch `sender` and global/static state. +class GDUtilsBadgeHandler : public CCObject { +public: + static GDUtilsBadgeHandler* get() { + static auto* inst = [] { + auto* h = new GDUtilsBadgeHandler(); + h->retain(); + return h; + }(); + return inst; + } + + void onBadgeClick(CCObject* sender) { + auto* btn = typeinfo_cast(sender); + if (!btn) return; + + // Primary: tag set directly on this button instance (original button click). + int tag = btn->getTag(); + if (auto it = s_tagToCallback.find(tag); it != s_tagToCallback.end()) { + it->second(); + return; + } + + // Fallback: sprite frame lookup (BadgesAPI popup copy, tag is -1). + if (auto* spr = typeinfo_cast(btn->getNormalImage())) { + if (auto fit = s_frameToTag.find(spr->displayFrame()); fit != s_frameToTag.end()) { + if (auto it = s_tagToCallback.find(fit->second); it != s_tagToCallback.end()) + it->second(); + } + } + } +}; + +static CCMenuItemSpriteExtra* makeBadgeButton(CCNode* normalSprite, std::string const& id, std::function callback) { + int tag = ++s_nextBadgeTag; + s_tagToCallback[tag] = std::move(callback); + if (auto* spr = typeinfo_cast(normalSprite)) + s_frameToTag[spr->displayFrame()] = tag; + auto* btn = CCMenuItemSpriteExtra::create(normalSprite, GDUtilsBadgeHandler::get(), menu_selector(GDUtilsBadgeHandler::onBadgeClick)); + btn->setID(id); + btn->setTag(tag); + return btn; +} + +static void requestBadges(async::TaskHolder listener, std::function callback) { + if (!s_cachedBadgesResponse.empty()) { + callback(s_cachedBadgesResponse); + } else { + listener.spawn(web::WebRequest().get("https://clarifygdps.com/gdutils/gdutils_roles.php?version=1.0"), [callback](web::WebResponse value) { + if (value.ok()) { + auto res = value.string().unwrapOrDefault(); + callback(std::move(res)); + } else { + log::error("Failed to get GDUtils badges: {}", value.error()); + } + }); + } +} + +static void onRobTopBadgePressed() { + FLAlertLayer::create( + nullptr, + "RobTop Games", + R"text( +RobTop is the creator and the main developer of Geometry Dash. + +He is the only developer of the game and is responsible for all the updates and content that is added to the game. + )text", + "OK", + nullptr, + 300.0f + )->show(); +} +static void onModBadgePressed(int badgeID) { + switch (badgeID) { + case 1: + #ifndef GEODE_IS_ANDROID + FLAlertLayer::create( + nullptr, + "Geometry Dash Moderator", + R"text( +A Geometry Dash Moderator is a user that has been chosen by RobTop and other Moderators on the team by suggestions. + +Their first task is to suggest levels to be rated to RobTop, the current developer of the game and the maintainer of the level rating system, he is the only one that can rate levels. + +How to become a Geometry Dash Moderator? + +Many community members want to become a Moderator to be able to suggest levels for a rating. Similar to rating, Moderator promotions are solely done by RobTop himself on a case-by-case basis, so there are no clear steps to getting it. Here are some general criteria: +- Be nice. +- Be active in the community. +- Be trustworthy. +- Be able to judge levels well. + +If you display these qualities over time, there is a chance that other Moderators may suggest you to RobTop. Of course, showing that you are qualified may be difficult if you do not share circles with pre-existing Moderators. If you are interested, you can apply to join the team using our application form. Make sure you read the information in it clearly before submitting. Here is the link: + +https://forms.gle/XyRGtFzD3hshDUQV7 + )text", + "OK", + nullptr, + 400.0f, + true, + 100.0f, + 1.0f + )->show(); + #else + FLAlertLayer::create( + nullptr, + "Geometry Dash Moderator", + R"text( +A Geometry Dash Moderator is a user that has been chosen by RobTop and other Moderators on the team by suggestions. + +Their first task is to suggest levels to be rated to RobTop, the current developer of the game and the maintainer of the level rating system, he is the only one that can rate levels. + )text", + "OK", + nullptr, + 400.0f, + true, + 100.0f, + 1.0f + )->show(); + + #endif + break; + case 2: + #ifndef GEODE_IS_ANDROID // android height broken + FLAlertLayer::create( + nullptr, + "Geometry Dash Elder Moderator", + R"text( +A Geometry Dash Elder Moderator is a user that has been chosen by RobTop and other Moderators on the team by suggestions and was already a Geometry Dash Moderator before his promotion. They are the pillars of the moderation team. + +Their first task is to suggest levels to be rated to RobTop, the current developer of the game and the maintainer of the level rating system, which he is the only one that can rate levels. But they also have the power to moderate comments, whitelists Newgrounds artists and unlocks updates for old rated levels. + +How to become a Geometry Dash Moderator? + +Many community members want to become a Moderator to be able to suggest levels for a rating. Similar to rating, Moderator promotions are solely done by RobTop himself on a case-by-case basis, so there are no clear steps to getting it. Here are some general criteria: +- Be nice. +- Be active in the community. +- Be trustworthy. +- Be able to judge levels well. + +If you display these qualities over time, there is a chance that other Moderators may suggest you to RobTop. Of course, showing that you are qualified may be difficult if you do not share circles with pre-existing Moderators. If you are interested, you can apply to join the team using our application form. Make sure you read the information in it clearly before submitting. Here is the link: + +https://forms.gle/XyRGtFzD3hshDUQV7 + )text", + "OK", + nullptr, + 400.0f, + true, + 100.0f, + 1.0f + )->show(); + #else + FLAlertLayer::create( + nullptr, + "Geometry Dash Elder Moderator", + R"text( +A Geometry Dash Elder Moderator is a user that has been chosen by RobTop and other Moderators on the team by suggestions and was already a Geometry Dash Moderator before his promotion. They are the pillars of the moderation team. + +Their first task is to suggest levels to be rated to RobTop, the current developer of the game and the maintainer of the level rating system, which he is the only one that can rate levels. But they also have the power to moderate comments, whitelists Newgrounds artists and unlocks updates for old rated levels. + )text", + "OK", + nullptr, + 400.0f, + true, + 100.0f, + 1.0f + )->show(); + #endif + break; + case 3: + FLAlertLayer::create( + nullptr, + "Geometry Dash Leaderboard Moderator", + R"text( +A Geometry Dash Leaderboard Moderator is a user that has been chosen by RobTop and other Leaderboard Moderators on the team by suggestions. + +Their first task is to moderate the Top 100 / Global leaderboard (as well as level-specific ones) and ban cheaters to keep the leaderboards clean. + +How to become a Geometry Dash Leaderboard Moderator? + +If you are interested, you can apply to join the team using our application form. Make sure you read the information in it clearly before submitting. Here is the link: + +https://docs.google.com/forms/d/e/1FAIpQLSfrJyIVM7KzPyTgzGZ0CSuGBPv40160W9I6bPiMgLRawjJJBg/viewform + )text", + "OK", + nullptr, + 500.0f, + true, + 40.0f, + 1.0f + )->show(); + break; + } +} + +// Mod badges descriptions & GDUtils dev badge +class $modify(GDUtilsProfilePage, ProfilePage) { + struct Fields { + async::TaskHolder m_listener; + }; + + void handleResponse(std::string result, int accountID) { + auto menu = m_mainLayer->getChildByID("username-menu"); + if (!menu) return; + if (result.empty()) return; + s_cachedBadgesResponse = result; + std::vector users = geode::utils::string::split(result, "|"); + for (auto user : users) { + std::vector data = geode::utils::string::split(user, "?"); + int badge = 0; + int accountID_data = 0; + std::string badge_id = ""; + std::string badge_sprite = ""; + float badge_scale = 1.0f; + std::string alertTitle = ""; + std::string alertDesc = ""; + float alertWidth = 300.0f; + bool isKofi = false; + while (data.size() > 0) { + std::string id = data[0]; + std::string name = data[1]; + if (id == "1") { + accountID_data = numFromString(name).unwrapOrDefault(); + } else if (id == "3") { + badge = numFromString(name).unwrapOrDefault(); + } else if (id == "4") { + badge_sprite = name; + } else if (id == "5") { + badge_id = name; + } else if (id == "6") { + badge_scale = numFromString(name).unwrapOrDefault(); + } else if (id == "8") { + alertTitle = name; + } else if (id == "9") { + alertDesc = name; + } else if (id == "10") { + alertWidth = numFromString(name).unwrapOrDefault(); + } else if (id == "11") { + isKofi = name == "1"; + } + data.erase(data.begin()); + data.erase(data.begin()); + } + if (accountID_data == accountID) { + if (!m_mainLayer->getChildByIDRecursive(badge_id)) { + auto* sprite = Build::createSpriteName(fmt::format("{}"_spr, badge_sprite).c_str()) + .scale(badge_scale) + .collect(); + auto* btn = makeBadgeButton(sprite, badge_id, [title = alertTitle, desc = alertDesc, isKofi, width = alertWidth]() { + if (isKofi) { + geode::createQuickPopup(title.c_str(), geode::utils::string::replace(desc, "\\n", "\n").c_str(), "OK", "Ko-Fi", + [](auto, bool btn2) { if (btn2) geode::utils::web::openLinkInBrowser("https://ko-fi.com/gdutils"); }, width); + } else { + FLAlertLayer::create(nullptr, title.c_str(), desc.c_str(), "OK", nullptr, width)->show(); + } + }); + menu->addChild(btn); + menu->updateLayout(); + } + } + } + } + + void loadPageFromUserInfo(GJUserScore* score) { + ProfilePage::loadPageFromUserInfo(score); + if (m_mainLayer) { + auto menu = m_mainLayer->getChildByID("username-menu"); + if (!menu) return; + if (auto modBadge = menu->getChildByID("mod-badge")) { + modBadge->removeFromParentAndCleanup(true); + if (score->m_userName == "RobTop" && Mod::get()->getSettingValue("customBadges")) { + auto* spr = Build::createSpriteName("robtop_badge.png"_spr).collect(); + menu->addChild(makeBadgeButton(spr, "mod-badge", []() { onRobTopBadgePressed(); })); + } else { + int badgeID = score->m_modBadge; + auto* spr = Build::createSpriteName(fmt::format("modBadge_0{}_001.png", badgeID).c_str()).collect(); + menu->addChild(makeBadgeButton(spr, "mod-badge", [badgeID]() { onModBadgePressed(badgeID); })); + } + } + if (Mod::get()->getSettingValue("customBadges")) { + if (!s_cachedBadgesResponse.empty()) { + handleResponse(s_cachedBadgesResponse, score->m_accountID); + } else { + m_fields->m_listener.spawn(web::WebRequest().get("https://clarifygdps.com/gdutils/gdutils_roles.php?version=1.0"), [this, accountID = std::move(score->m_accountID)](web::WebResponse value) { + if (value.ok()) { + auto res = value.string().unwrapOrDefault(); + handleResponse(std::move(res), accountID); + } else { + log::error("Failed to get GDUtils badges: {}", value.error()); + } + }); + } + } + menu->updateLayout(); + } + } +}; + +// Comments +#include + +std::string badgesDataComments = ""; + +int hexStringToInt(const std::string& hexStr) { + int value; + std::istringstream iss(hexStr); + iss >> std::hex >> value; + return value; +} + +class $modify(CustomBadgesCommentCell, CommentCell) { + struct Fields { + async::TaskHolder m_listener; + }; + + void handleResponse(std::string result, int commentID) { + auto menu = m_mainLayer->getChildByIDRecursive("username-menu"); + if (!menu) return; + if (this->m_accountComment) return; + if (result.empty()) return; + s_cachedBadgesResponse = result; + std::vector users = geode::utils::string::split(result, "|"); + + CommentCell* cell = this; + int accountID = cell->m_comment->m_accountID; + bool colorSet = false; + + for (auto user : users) { + std::vector data = geode::utils::string::split(user, "?"); + int badge = 0; + int accountID_data = 0; + std::string badge_id = ""; + std::string badge_sprite = ""; + float badge_scale = 1.0f; + std::string alertTitle = ""; + std::string alertDesc = ""; + float alertWidth = 300.0f; + bool isKofi = false; + ccColor3B color = { 255, 255, 255 }; + + while (data.size() > 0) { + std::string id = data[0]; + std::string name = data[1]; + if (id == "1") { + accountID_data = geode::utils::numFromString(name).unwrapOrDefault(); + } else if (id == "3") { + badge = geode::utils::numFromString(name).unwrapOrDefault(); + } else if (id == "4") { + badge_sprite = name; + } else if (id == "5") { + badge_id = name; + } else if (id == "7") { + badge_scale = geode::utils::numFromString(name).unwrapOrDefault(); + } else if (id == "8") { + alertTitle = name; + } else if (id == "9") { + alertDesc = name; + } else if (id == "10") { + alertWidth = geode::utils::numFromString(name).unwrapOrDefault(); + } else if (id == "11") { + isKofi = name == "1"; + } else if (id == "12") { + // Get color from HEX + color = ccc3( + hexStringToInt(name.substr(0, 2)), + hexStringToInt(name.substr(2, 2)), + hexStringToInt(name.substr(4, 2)) + ); + } + data.erase(data.begin()); + data.erase(data.begin()); + } + + if (accountID_data == accountID) { + bool isCustomColor = (color.r != 255 || color.g != 255 || color.b != 255); + if (isCustomColor && !colorSet) { + if (auto textArea = m_mainLayer->getChildByType(0)) { + CCArrayExt children = textArea->m_label->getChildren(); + for (auto label : children) label->setColor(color); + colorSet = true; + } else if (auto commentText = static_cast(m_mainLayer->getChildByID("comment-text-label"))) { + commentText->setColor(color); + cell->m_comment->m_color = color; + colorSet = true; + } + } + if (!m_mainLayer->getChildByIDRecursive(badge_id)) { + auto* sprite = Build::createSpriteName(fmt::format("{}"_spr, badge_sprite).c_str()) + .scale(badge_scale) + .collect(); + auto* btn = makeBadgeButton(sprite, badge_id, [title = alertTitle, desc = alertDesc, isKofi, width = alertWidth]() { + if (isKofi) { + geode::createQuickPopup(title.c_str(), geode::utils::string::replace(desc, "\\n", "\n").c_str(), "OK", "Ko-Fi", + [](auto, bool btn2) { if (btn2) geode::utils::web::openLinkInBrowser("https://ko-fi.com/gdutils"); }, width); + } else { + FLAlertLayer::create(nullptr, title.c_str(), desc.c_str(), "OK", nullptr, width)->show(); + } + }); + if (cell->getChildByIDRecursive("percentage-label")) { + menu->insertBefore(btn, cell->getChildByIDRecursive("percentage-label")); + } else { + menu->addChild(btn); + } + menu->updateLayout(); + } + } + } + } + + void loadFromComment(GJComment* comment) { + CommentCell::loadFromComment(comment); + if (comment->m_commentDeleted) return; + auto menu = m_mainLayer->getChildByIDRecursive("username-menu"); + if (!menu) return; + if (auto modBadge = menu->getChildByID("mod-badge")) { + modBadge->removeFromParentAndCleanup(true); + CCMenuItemSpriteExtra* badgeBtn; + if (m_comment->m_userName == "RobTop" && Mod::get()->getSettingValue("customBadges")) { + auto* spr = Build::createSpriteName("robtop_badge.png"_spr).scale(0.75f).collect(); + badgeBtn = makeBadgeButton(spr, "mod-badge", []() { onRobTopBadgePressed(); }); + } else { + int badgeID = comment->m_modBadge; + auto* spr = Build::createSpriteName(fmt::format("modBadge_0{}_001.png", badgeID).c_str()).scale(0.6f).collect(); + badgeBtn = makeBadgeButton(spr, "mod-badge", [badgeID]() { onModBadgePressed(badgeID); }); + } + if (getChildByIDRecursive("percentage-label")) { + menu->insertBefore(badgeBtn, getChildByIDRecursive("percentage-label")); + } else { + menu->addChild(badgeBtn); + } + } + if (Mod::get()->getSettingValue("customBadges")) { + if (!s_cachedBadgesResponse.empty()) { + handleResponse(s_cachedBadgesResponse, m_comment->m_commentID); + } else { + m_fields->m_listener.spawn(web::WebRequest().get("https://clarifygdps.com/gdutils/gdutils_roles.php?version=1.0"), [this](web::WebResponse value) { + if (value.ok()) { + auto res = value.string().unwrapOrDefault(); + handleResponse(std::move(res), m_comment->m_commentID); + } else { + log::error("Failed to get GDUtils badges: {}", value.error()); + } + }); + } + } + menu->updateLayout(); + } +}; + +static void toggleHook(bool value) { + for (auto& hook : geode::Mod::get()->getHooks()) { + if (hook->getDisplayName().starts_with("ProfilePage") || hook->getDisplayName().starts_with("CommentCell")) { + (void)(value ? hook->enable() : hook->disable()); + } + } +} +$execute { + listenForSettingChanges("clickableBadges", [](bool value) { + log::info("Clickable Badges changed to {}", value); + toggleHook(value); + }); +} +$on_mod(Loaded) { + if (!Mod::get()->getSettingValue("clickableBadges")) { + toggleHook(false); + } +} diff --git a/src/hooks/CustomScoreCell.cpp b/src/hooks/CustomScoreCell.cpp new file mode 100644 index 0000000..0734709 --- /dev/null +++ b/src/hooks/CustomScoreCell.cpp @@ -0,0 +1,202 @@ +#include +#include +#include +#include + +class $modify(CustomScoreCell, GJScoreCell) { + void loadFromScore(GJUserScore* score) { + GJScoreCell::loadFromScore(score); + + CCLayer* layer = static_cast(this->getChildren()->objectAtIndex(1)); + if (!layer) return; + + std::string data_flag = MoreLeaderboards::data_response_moreLB; + if (data_flag == "") return; + + RowLayout* layout = RowLayout::create(); + layout->setGap(3); + layout->setAxisAlignment(AxisAlignment::Start); + layout->setCrossAxisOverflow(true); + + CCMenu* menu = CCMenu::create(); + menu->setContentSize(CCSize(283, 21.580f)); + menu->setPosition(206, 42); + + auto starsLabel = static_cast(layer->getChildByIDRecursive("stars-label")); + starsLabel->setLayoutOptions(AxisLayoutOptions::create()->setAutoScale(true)->setScaleLimits(0, 0.5F)->setScalePriority(1)); + auto starsIcon = static_cast(layer->getChildByIDRecursive("stars-icon")); + starsIcon->setLayoutOptions(AxisLayoutOptions::create()->setAutoScale(true)->setScaleLimits(0, 0.5F)->setScalePriority(1)); + auto moonsLabel = static_cast(layer->getChildByIDRecursive("moons-label")); + moonsLabel->setLayoutOptions(AxisLayoutOptions::create()->setAutoScale(true)->setScaleLimits(0, 0.5F)->setScalePriority(1)); + auto moonsIcon = static_cast(layer->getChildByIDRecursive("moons-icon")); + moonsIcon->setLayoutOptions(AxisLayoutOptions::create()->setAutoScale(true)->setScaleLimits(0, 0.5F)->setScalePriority(1)); + + auto* playerNameItem = static_cast(layer->getChildByIDRecursive("player-name")); + std::string playerName = static_cast(playerNameItem->getChildren()->objectAtIndex(0))->getString(); + CCMenu* menu_playername = CCMenu::create(); + menu_playername->setContentSize(playerNameItem->getContentSize()); + menu_playername->setLayout(RowLayout::create()->setGap(3)->setAxisAlignment(AxisAlignment::Start)); + + auto playerNameBM = CCLabelBMFont::create(playerName.c_str(), "goldFont.fnt"); + auto playerNameBtn = CCMenuItemSpriteExtra::create( + playerNameBM, this, (SEL_MenuHandler)&CustomScoreCell::onViewProfile + ); + playerNameBtn->setLayoutOptions(AxisLayoutOptions::create()->setAutoScale(true)->setScaleLimits(0.5F, 0.8F)->setScalePriority(1)); + + std::vector dataString = MoreLeaderboards::getWords(data_flag, "#"); + std::vector users = MoreLeaderboards::getWords(dataString[0], "|"); + std::string count_diff = "0"; + + while (users.size() > 0) { + std::vector data_info = MoreLeaderboards::getWords(users[0], ":"); + while (data_info.size() > 0) { + std::string id = data_info[0]; + std::string info = data_info[1]; + if (id == "1") { + if (info != playerName) break; + } + if (id == "9989") { + count_diff = info; + } + if (id == "9990") { + if (info == "XX") break; + auto flagSpr = CCSprite::createWithSpriteFrameName((""_spr + info + ".png").c_str()); + flagSpr->setPosition({20, 15}); + flagSpr->setScaleY(20 / flagSpr->getContentHeight() * 0.50); + flagSpr->setScaleX(std::min(1.0f, 30 / flagSpr->getContentWidth())); + flagSpr->setLayoutOptions(AxisLayoutOptions::create()->setAutoScale(true)->setScalePriority(1)); + menu_playername->addChild(flagSpr); + } + data_info.erase(data_info.begin()); + data_info.erase(data_info.begin()); + } + users.erase(users.begin()); + } + + menu_playername->addChild(playerNameBtn); + menu_playername->updateLayout(); + + if (auto n = layer->getChildByID("stars-label")) n->removeFromParentAndCleanup(true); + if (auto n = layer->getChildByID("stars-icon")) n->removeFromParentAndCleanup(true); + if (auto n = layer->getChildByID("moons-label")) n->removeFromParentAndCleanup(true); + if (auto n = layer->getChildByID("moons-icon")) n->removeFromParentAndCleanup(true); + if (auto n = layer->getChildByID("main-menu")) n->removeFromParentAndCleanup(true); + + menu->addChild(menu_playername); + menu->addChild(starsLabel); + menu->addChild(starsIcon); + menu->addChild(moonsLabel); + menu->addChild(moonsIcon); + menu->setLayout(layout); + menu->updateLayout(); + + // find the main layer with stats + CCLayer* mainLayer = nullptr; + for (auto* child : this->getChildrenExt()) { + auto* search = typeinfo_cast(child); + if (search && search->getChildrenCount() > 2) { + mainLayer = search; + break; + } + } + if (!mainLayer) { layer->addChild(menu); return; } + auto statsMenu = mainLayer->getChildByIDRecursive("stats-menu"); + + if (!Loader::get()->isModLoaded("itzkiba.better_progression") && MoreLeaderboards::g_tab == StatsListType::BetterProgression) { + int currentEXP = LevelHelper::calculateTotalEXP(score); + int currentLevel = LevelHelper::getLevelFromEXP(currentEXP); + auto badgeSpr = SpriteHelper::createFullSprite(currentLevel); + badgeSpr->setPosition({75, 17.5}); + badgeSpr->setScale(0.62); + mainLayer->addChild(badgeSpr); + statsMenu->setScale(0.83); + statsMenu->setPositionX(statsMenu->getPositionX() + 13.f); + } + + auto makeClassicSpr = [](const char* base) { + auto s = CCSprite::createWithSpriteFrameName(base); + auto c = CCSprite::createWithSpriteFrameName("star_small01_001.png"); + c->setPositionX(30); c->setScale(1.2f); + s->addChild(c); + return s; + }; + auto makePlatformerSpr = [](const char* base) { + auto s = CCSprite::createWithSpriteFrameName(base); + auto m = CCSprite::createWithSpriteFrameName("moon_small01_001.png"); + m->setPositionX(30); m->setScale(1.2f); + s->addChild(m); + return s; + }; + auto pointercrate = CCSprite::createWithSpriteFrameName("diffIcon_06_btn_001.png"); + auto pc_text = CCLabelBMFont::create("PC", "goldFont.fnt"); + pc_text->setPosition(28, 0); pc_text->setScale(0.5f); + pointercrate->addChild(pc_text); + + if (statsMenu) { + const struct { const char* id; int z; } zmap[] = { + {"diamonds-label", 0}, {"diamonds-icon", 1}, + {"coins-label", 2}, {"coins-icon", 3}, + {"user-coins-label", 4}, {"user-coins-icon", 5}, + {"demons-label", 6}, {"demons-icon", 7}, + {"creator-points-label", 8}, {"creator-points-icon", 9}, + }; + for (auto& e : zmap) { + if (auto n = statsMenu->getChildByIDRecursive(e.id)) n->setZOrder(e.z); + } + } + + auto demon_icon = mainLayer->getChildByIDRecursive("demons-icon"); + auto demon_label = mainLayer->getChildByIDRecursive("demons-label"); + if (!demon_icon || !demon_label) { layer->addChild(menu); return; } + + auto demon_icon_pos = demon_icon->getPosition(); + auto demon_icon_scale = demon_icon->getScale(); + auto demon_icon_z = demon_icon->getZOrder(); + auto demon_icon_tag = demon_icon->getTag(); + auto demon_icon_layout = demon_icon->getLayoutOptions(); + auto demon_label_pos = demon_label->getPosition(); + auto demon_label_scale = demon_label->getScale(); + auto demon_label_z = demon_label->getZOrder(); + auto demon_label_tag = demon_label->getTag(); + auto demon_label_layout = demon_label->getLayoutOptions(); + + CCSprite* new_icon = nullptr; + switch (MoreLeaderboards::g_tab) { + case StatsListType::platformerDemonsEasy: new_icon = makePlatformerSpr("diffIcon_07_btn_001.png"); break; + case StatsListType::platformerDemonsMedium: new_icon = makePlatformerSpr("diffIcon_08_btn_001.png"); break; + case StatsListType::platformerDemonsHard: new_icon = makePlatformerSpr("diffIcon_06_btn_001.png"); break; + case StatsListType::platformerDemonsInsane: new_icon = makePlatformerSpr("diffIcon_09_btn_001.png"); break; + case StatsListType::platformerDemonsExtreme: new_icon = makePlatformerSpr("diffIcon_10_btn_001.png"); break; + case StatsListType::classicDemonsEasy: new_icon = makeClassicSpr("diffIcon_07_btn_001.png"); break; + case StatsListType::classicDemonsMedium: new_icon = makeClassicSpr("diffIcon_08_btn_001.png"); break; + case StatsListType::classicDemonsHard: new_icon = makeClassicSpr("diffIcon_06_btn_001.png"); break; + case StatsListType::classicDemonsInsane: new_icon = makeClassicSpr("diffIcon_09_btn_001.png"); break; + case StatsListType::classicDemonsExtreme: new_icon = makeClassicSpr("diffIcon_10_btn_001.png"); break; + case StatsListType::Pointercrate: new_icon = pointercrate; break; + default: break; + } + + if (new_icon && statsMenu) { + demon_icon->removeFromParent(); + new_icon->setPosition(demon_icon_pos); + new_icon->setScale(demon_icon_scale); + new_icon->setLayoutOptions(demon_icon_layout); + new_icon->setTag(demon_icon_tag); + new_icon->setZOrder(demon_icon_z); + statsMenu->addChild(new_icon); + + demon_label->removeFromParent(); + auto new_label = CCLabelBMFont::create(count_diff.c_str(), "bigFont.fnt"); + new_label->setPosition(demon_label_pos); + new_label->setScale(demon_label_scale); + new_label->setZOrder(demon_label_z); + new_label->setTag(demon_label_tag); + new_label->setLayoutOptions(demon_label_layout); + statsMenu->addChild(new_label); + statsMenu->updateLayout(); + } + + layer->addChild(menu); + layer->updateLayout(); + } +}; diff --git a/src/hooks/DailyLevelPage.cpp b/src/hooks/DailyLevelPage.cpp new file mode 100644 index 0000000..4c83823 --- /dev/null +++ b/src/hooks/DailyLevelPage.cpp @@ -0,0 +1,40 @@ +#include +#include +#include + +class $modify(EventPage, DailyLevelPage) { + bool init(GJTimedLevelType type) { + if (!DailyLevelPage::init(type)) return false; + + if (type != GJTimedLevelType::Event) return true; + + if (auto menu = this->m_mainLayer->getChildByIDRecursive("main-menu")) { + Build::createSpriteName("info_btn.png"_spr).intoMenuItem([]() { + EventInfoPopup::create()->show(); + }).pos(14,-194).parent(menu); + } + return true; + } +}; + +static void toggleHook(bool value) { + for (auto& hook : geode::Mod::get()->getHooks()) { + if (hook->getDisplayName().starts_with("DailyLevelPage")) { + (void)(value ? hook->enable() : hook->disable()); + } + } +} + +$execute { + listenForSettingChanges("eventLevelInfo", [](bool value) { + log::info("Event Level Info changed to {}", value); + toggleHook(value); + }); +} + +$on_mod(Loaded) { + if (!Mod::get()->getSettingValue("eventLevelInfo")) { + toggleHook(false); + } +} + diff --git a/src/hooks/FriendsProfilePage.cpp b/src/hooks/FriendsProfilePage.cpp new file mode 100644 index 0000000..7f30924 --- /dev/null +++ b/src/hooks/FriendsProfilePage.cpp @@ -0,0 +1,153 @@ +#include +#include +#include + +class $modify(FriendPage, FriendsProfilePage) { + bool init(UserListType type) { + if (!FriendsProfilePage::init(type)) return false; + Build::createSpriteName("gj_findBtn_001.png").intoMenuItem([this]() { + if (!m_users) { + youhavenofriends: + FLAlertLayer::create(nullptr, + "Error", + "You have no friends!", + "OK", + nullptr, + 200.0F + )->show(); + return; + } + if (!m_listLayer->m_list) + return; + auto customList = m_listLayer->m_list->m_tableView; + if (customList == nullptr) return; + if (customList->m_contentLayer && customList->m_contentLayer->getChildrenCount() <= 0) { + goto youhavenofriends; + } + SearchUserLayer::create(this)->show(); + }).pos(15, -135).parent(m_buttonMenu); + return true; + } + void setupUsersBrowser(cocos2d::CCArray * users, UserListType type) { + FriendsProfilePage::setupUsersBrowser(users, type); + m_buttonMenu->removeChildByID("friendsScrollBar"_spr); + } + virtual void getUserListFinished(cocos2d::CCArray* a1, UserListType a2) { + FriendsProfilePage::getUserListFinished(a1,a2); + // Add custom scrollbar + auto scrollBar = Scrollbar::create(m_listLayer->m_list->m_tableView); + scrollBar->setPosition(390, -140); + scrollBar->setID("friendsScrollBar"_spr); + m_buttonMenu->addChild(scrollBar); + } + virtual void onUpdate(UserListType a1) { + FriendsProfilePage::forceReloadList(a1); + m_buttonMenu->removeChildByID("friendsScrollBar"_spr); + } +}; + +void SearchUserLayer::onValidate() { + if (auto obj = m_friendPage.lock()) { + std::string username = input_username->getString(); + // If we couldn't find the comment list layer, return + if (obj->m_listLayer == nullptr) { + // safeguard from crashing + FLAlertLayer::create(nullptr, + "Error", + "The mod could not find the GJCommentListLayer layer. Please either try again later, removing mods that may be interfering with the scene, or report this to the developers.", + "OK", + nullptr, + 350.0F + )->show(); + return; + } + if (!obj->m_users) { +youhavenofriends: + FLAlertLayer::create(nullptr, + "Error", + "You have no friends!", + "OK", + nullptr, + 200.0F + )->show(); + return; + } + if (!obj->m_listLayer->m_list) + return; + auto customList = obj->m_listLayer->m_list->m_tableView; + + // If the list is null, return + if (customList == nullptr) return; + + if (customList->m_contentLayer && customList->m_contentLayer->getChildrenCount() <= 0) { + goto youhavenofriends; + } + + auto contentLayer = customList->m_contentLayer; + + int counter_page = 0; + bool found = false; + + auto cells = CCArrayExt(customList->m_contentLayer->getChildren()); + + // Iterate through all cells in the list + for (auto cell : cells) { + std::string inputUsername = geode::utils::string::toLower(cell->m_userScore->m_userName); + + // If username is found in the cell's username (case insensitive) + if (inputUsername.find(geode::utils::string::toLower(username)) != std::string::npos) { + customList->scrollLayer(-9999999); + customList->scrollLayer(counter_page); + found = true; + // Pulse only one time cell color animation + if (auto layer = cell->getChildByType(0)) { + auto originalColor = layer->getColor(); + auto tintTo1 = CCTintTo::create(0.2f, 0, 255, 0); // Change to green + auto tintTo2 = CCTintTo::create(0.5f, originalColor.r, originalColor.g, originalColor.b); // Change back to original color + auto sequence = CCSequence::create(tintTo1, tintTo2, nullptr); + cell->getChildByType(0)->runAction(sequence); + } + break; + } + counter_page += 45; + } + + // If user not found, show alert + if (!found) { + std::string str = username; + FLAlertLayer::create(nullptr, + "Error", + "User not found : " + str, + "OK", + nullptr, + 200.0F + )->show(); + } + } + Popup::onClose(nullptr); +} + +static void toggleHook(bool value) { + for (auto& hook : geode::Mod::get()->getHooks()) { + if (hook->getDisplayName().starts_with("FriendsProfilePage")) { + if (value) { + (void)hook->enable(); + } else { + (void)hook->disable(); + } + } + } +} + +$execute { + listenForSettingChanges("friendSearch", [](bool value) { + log::info("Friend Search changed to {}", value); + toggleHook(value); + }); +} + +$on_mod(Loaded) { + if (!Mod::get()->getSettingValue("friendSearch")) { + toggleHook(false); + } +} diff --git a/src/hooks/GJGarageLayer.cpp b/src/hooks/GJGarageLayer.cpp new file mode 100644 index 0000000..018508d --- /dev/null +++ b/src/hooks/GJGarageLayer.cpp @@ -0,0 +1,74 @@ +#include +#include +class $modify(ItemInfoPopup) { + bool init(int id, UnlockType type) { + if (!ItemInfoPopup::init(id, type)) return false; + if (auto scene = CCScene::get()) { + if (scene->getChildByID("GJGarageLayer")) { + GameManager* gm = GameManager::sharedState(); + GJItemIcon* node = m_mainLayer->getChildByType(0); + if (node && node->m_isIcon) { + auto player = static_cast(node->m_player); + player->setColor(gm->colorForIdx(gm->getPlayerColor())); + player->setSecondColor(gm->colorForIdx(gm->getPlayerColor2())); + player->m_glowColor = gm->colorForIdx(gm->getPlayerGlowColor()); + + Build::createSpriteName("GJ_checkOff_001.png").scale(.8f).child( + Build::create("P1", "bigFont.fnt").scale(.525f).pos(15, 17) + ).intoMenuItem([player]() { + GameManager* gm = GameManager::sharedState(); + player->setColor(gm->colorForIdx(gm->getPlayerColor())); + player->setSecondColor(gm->colorForIdx(gm->getPlayerColor2())); + }).pos(-128, -40).id("p1-button"_spr).parent(m_buttonMenu); + + Build::createSpriteName("GJ_checkOff_001.png").scale(.8f).child( + Build::create("P2", "bigFont.fnt").scale(.525f).pos(15, 17) + ).intoMenuItem([player]() { + GameManager* gm = GameManager::sharedState(); + player->setColor(gm->colorForIdx(gm->getPlayerColor2())); + player->setSecondColor(gm->colorForIdx(gm->getPlayerColor())); + }).pos(-99, -40).id("p2-button"_spr).parent(m_buttonMenu); + + Build::createSpriteName("GJ_checkOff_001.png").scale(.8f).child( + Build::create("G", "bigFont.fnt").scale(.525f).pos(15, 17) + ).intoMenuItem([player]() { + GameManager* gm = GameManager::sharedState(); + if (!player->m_hasGlowOutline) { + player->setGlowOutline(gm->colorForIdx(gm->getPlayerGlowColor())); + } else { + player->disableGlowOutline(); + } + }).pos(-69, -40).id("glow-button"_spr).parent(m_buttonMenu); + } + + } + } + + return true; + } +}; + +static void toggleHook(bool value) { + for (auto& hook : geode::Mod::get()->getHooks()) { + if (hook->getDisplayName().starts_with("ItemInfoPopup")) { + if (value) { + (void)hook->enable(); + } else { + (void)hook->disable(); + } + } + } +} + +$execute { + listenForSettingChanges("previewIcons", [](bool value) { + log::info("Preview Icons changed to {}", value); + toggleHook(value); + }); +} + +$on_mod(Loaded) { + if (!Mod::get()->getSettingValue("previewIcons")) { + toggleHook(false); + } +} diff --git a/src/hooks/GauntletSelectLayer.cpp b/src/hooks/GauntletSelectLayer.cpp new file mode 100644 index 0000000..1e4f94a --- /dev/null +++ b/src/hooks/GauntletSelectLayer.cpp @@ -0,0 +1,284 @@ +#include +#include + +struct GauntletParticles { + std::string particle; + CCPoint pos; + CCPoint scale = CCPoint(1.0f, 1.0f); + float rotation = 0.0f; + int zOrder = 1; + bool useGauntletPos = true; +}; + +struct NewGauntlet { + std::vector particles; + std::string background; + float bgOffsetY = 0.0f; + float scaleBg = 1.0f; + float scaleGauntlet = 0.0f; + CCPoint gauntletPos; + float gauntletRotation = 0.0f; + bool gauntletFlipX = false; + int gauntletZOrder = 2; + bool reverseGauntlet = false; + int itemZOrder = 0; +}; + +template<> +struct matjson::Serialize { + static geode::Result fromJson(matjson::Value const& value) { + NewGauntlet data; + GEODE_UNWRAP_INTO(data.background, value["background"]["sprite"].asString()); + GEODE_UNWRAP_INTO(data.scaleBg, value["background"]["scale"].asDouble()); + + if (value["background"].contains("offsetY")) { + data.bgOffsetY = static_cast(value["background"]["offsetY"].asDouble().unwrapOrDefault()); + } + if (value.contains("reverseGauntlet")) { + data.reverseGauntlet = value["reverseGauntlet"].asBool().unwrapOrDefault(); + } + if (value.contains("itemZOrder")) { + data.itemZOrder = value["itemZOrder"].asInt().unwrapOrDefault(); + } + if (value.contains("gauntlet")) { + auto const& g = value["gauntlet"]; + if (g.contains("position")) { + GEODE_UNWRAP_INTO(auto gPos, g["position"].asArray()); + data.gauntletPos = CCPoint( + static_cast(gPos.at(0).asDouble().unwrapOrDefault()), + static_cast(gPos.at(1).asDouble().unwrapOrDefault()) + ); + } + GEODE_UNWRAP_INTO(data.scaleGauntlet, g["scale"].asDouble()); + if (g.contains("zOrder")) { + data.gauntletZOrder = g["zOrder"].asInt().unwrapOrDefault(); + } + if (g.contains("rotation")) { + data.gauntletRotation = static_cast(g["rotation"].asDouble().unwrapOrDefault()); + } + if (g.contains("flipX")) { + data.gauntletFlipX = g["flipX"].asBool().unwrapOrDefault(); + } + } + if (value.contains("particles")) { + GEODE_UNWRAP_INTO(auto particles, value["particles"].asArray()); + for (auto const& p : particles) { + GauntletParticles pd; + GEODE_UNWRAP_INTO(pd.particle, p["string"].asString()); + + auto posOpt = p["position"].asArray(); + if (posOpt.isOk()) { + auto const& pos = posOpt.unwrap(); + pd.pos = CCPoint( + static_cast(pos.at(0).asDouble().unwrapOrDefault()), + static_cast(pos.at(1).asDouble().unwrapOrDefault()) + ); + pd.useGauntletPos = false; + } + if (p.contains("scale")) { + GEODE_UNWRAP_INTO(auto sc, p["scale"].asArray()); + pd.scale = CCPoint( + static_cast(sc.at(0).asDouble().unwrapOrDefault()), + static_cast(sc.at(1).asDouble().unwrapOrDefault()) + ); + } + if (p.contains("zOrder")) { + pd.zOrder = p["zOrder"].asInt().unwrapOrDefault(); + } + if (p.contains("rotation")) { + pd.rotation = static_cast(p["rotation"].asDouble().unwrapOrDefault()); + } + data.particles.push_back(std::move(pd)); + } + } + return geode::Ok(data); + } +}; + +class $modify(CustomGauntletSelectLayer, GauntletSelectLayer) { + void reverseGauntlet(GauntletNode* node) { + if (!node->m_gauntletInfoNode) return; + if (auto checkmark = node->getChildByID("checkmark-sprite")) { + checkmark->setPositionY(78); + if (auto shadow = node->getChildByID("checkmark-shadow-sprite")) shadow->setPositionY(78); + } + if (auto label_reward = node->m_gauntletInfoNode->getChildByID("reward-label")) { + label_reward->setPositionY(50); + if (auto s = node->m_gauntletInfoNode->getChildByID("reward-shadow-label")) s->setPositionY(50); + if (auto chest = static_cast(node->m_gauntletInfoNode->getChildByID("chest-sprite"))) { + chest->setPositionY(80); + chest->setFlipY(true); + } + if (auto chest_s = static_cast(node->m_gauntletInfoNode->getChildByID("chest-shadow-sprite"))) { + chest_s->setPositionY(80); + chest_s->setFlipY(true); + } + } + if (auto lp = node->m_gauntletInfoNode->getChildByID("gauntlet-progress-label")) lp->setPositionY(29); + if (auto lps = node->m_gauntletInfoNode->getChildByID("gauntlet-progress-shadow-label")) lps->setPositionY(29); + } + + bool init(int p0) { + if (!GauntletSelectLayer::init(p0)) return false; + if (auto menu = this->getChildByIDRecursive("bottom-right-menu")) { + Build::createSpriteName("GJ_infoIcon_001.png").color(236, 149, 19).intoMenuItem([]() { + FLAlertLayer::create( + nullptr, + "Gauntlets redesign", + R"text( +All new designs for Gauntlets are made by xvia and brift. +Particles are made by GammaReXx. + +Thanks for their contributions! + )text", + "OK", + nullptr, + 300.0f + )->show(); + }).id("particle-info-button"_spr).zOrder(10).with([](CCNode* node) { + auto* p = GameToolbox::particleFromString( + "26a-1a1.66a0.3a30a90a180a14a0a1a1a0a7a0a0a0a0a2a1a0a0a1a0a0.568627a0a0.12549a0a1a0a1a1a0a0a1a0a0.501961a0a0a0a1a0a0a0a0.46a0a0a0a0a0a0a0a0a2a1a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0", + nullptr, false + ); + node->addChildAtPosition(p, Anchor::Center); + p->setZOrder(9); + }).parent(menu); + menu->updateLayout(); + } + return true; + } + + void setupGauntlets() { + GauntletSelectLayer::setupGauntlets(); + if (!m_scrollLayer) return; + + auto res = file::readJson(Mod::get()->getResourcesDir() / "particles.json"); + if (res.isErr()) { + log::error("Couldn't read gauntlets/particles.json: {}", res.unwrapErr()); + return; + } + auto const& json = res.unwrap(); + auto const scaleFactor = 4.f / CCDirector::get()->getContentScaleFactor(); + + for (int i = 0; i < m_scrollLayer->m_pages->count(); i++) { + auto* page = static_cast( + static_cast(m_scrollLayer->m_pages->objectAtIndex(i)) + ->getChildren()->objectAtIndex(0) + )->getChildren(); + + for (int j = 0; j < page->count(); j++) { + auto* item = static_cast(page->objectAtIndex(j)); + + if (j == 0 && page->count() > 1) { + item->setPositionX(item->getPositionX() - 25.0f); + } else if (j == 1 && page->count() == 2) { + item->setPositionX(item->getPositionX() + 25.0f); + } else if (j == 2) { + item->setPositionX(item->getPositionX() + 25.0f); + } + + auto* node = static_cast(item->getChildByIDRecursive("gauntlet-node")); + auto* label = static_cast(node->getChildByID("gauntlet-name-label")); + auto* label_shadow = node->getChildByID("gauntlet-name-shadow-label"); + auto* label_gauntlet = node->getChildByID("gauntlet-label"); + auto* label_shadow_gauntlet = node->getChildByID("gauntlet-shadow-label"); + auto* bg = node->getChildByID("background"); + auto* gauntlet_node = node->m_gauntletInfoNode; + auto* gauntlet = static_cast(gauntlet_node->getChildByID("gauntlet-sprite")); + auto* gauntlet_shadow = gauntlet_node->getChildByID("gauntlet-shadow-sprite"); + + bg->setVisible(false); + label->setVisible(false); + label_shadow->setVisible(false); + label_gauntlet->setVisible(false); + label_shadow_gauntlet->setVisible(false); + gauntlet->setVisible(false); + gauntlet_shadow->setVisible(false); + + std::string gauntletName = label->getString(); + + auto restoreVisibility = [&]() { + bg->setVisible(true); + label->setVisible(true); + label_shadow->setVisible(true); + label_gauntlet->setVisible(true); + label_shadow_gauntlet->setVisible(true); + gauntlet->setVisible(true); + gauntlet_shadow->setVisible(true); + }; + + if (!json.contains(gauntletName)) { + restoreVisibility(); + continue; + } + + auto gdOpt = matjson::Serialize::fromJson(json[gauntletName]); + if (gdOpt.isErr()) { + log::warn("Couldn't parse gauntlet '{}': {}", gauntletName, gdOpt.unwrapErr()); + restoreVisibility(); + continue; + } + auto const& gd = gdOpt.unwrap(); + + auto bgPos = bg->getPosition(); + bgPos.y += gd.bgOffsetY; + + auto* bgSprite = CCSprite::create(fmt::format("{}"_spr, gd.background).c_str()); + bgSprite->setPosition(bgPos); + bgSprite->setScale(gd.scaleBg / scaleFactor); + bgSprite->setZOrder(0); + bgSprite->setID("gauntlet-background"_spr); + node->addChild(bgSprite); + + if (gd.itemZOrder != 0) item->setZOrder(gd.itemZOrder); + if (gd.reverseGauntlet) reverseGauntlet(node); + + if (gd.scaleGauntlet != 0.f) { + gauntlet->setVisible(true); + gauntlet->setPosition(gd.gauntletPos); + gauntlet->setScale(gd.scaleGauntlet); + if (gd.gauntletRotation != 0.f) gauntlet->setRotation(gd.gauntletRotation); + if (gd.gauntletFlipX) gauntlet->setFlipX(true); + gauntlet_node->setZOrder(gd.gauntletZOrder); + } + + for (size_t k = 0; k < gd.particles.size(); k++) { + auto const& pd = gd.particles[k]; + auto* p = GameToolbox::particleFromString(pd.particle, nullptr, false); + node->addChild(p); + p->setZOrder(pd.zOrder); + p->setPosition(pd.useGauntletPos ? gauntlet->getPosition() : pd.pos); + p->setScaleX(pd.scale.x); + p->setScaleY(pd.scale.y); + if (pd.rotation != 0.f) p->setRotation(pd.rotation); + p->setID(fmt::format("gauntlet-particles-{}"_spr, k + 1)); + } + } + } + } +}; + +static void toggleHook(bool value) { + for (auto& hook : geode::Mod::get()->getHooks()) { + if (hook->getDisplayName().starts_with("GauntletSelectLayer")) { + if (value) { + (void)hook->enable(); + } else { + (void)hook->disable(); + } + } + } +} + +$execute { + listenForSettingChanges("gauntletDesign", [](bool value) { + log::info("Gauntlet Design changed to {}", value); + toggleHook(value); + }); +} + +$on_mod(Loaded) { + if (!Mod::get()->getSettingValue("gauntletDesign")) { + toggleHook(false); + } +} diff --git a/src/hooks/LeaderboardsLayer.cpp b/src/hooks/LeaderboardsLayer.cpp new file mode 100644 index 0000000..6fb6e3b --- /dev/null +++ b/src/hooks/LeaderboardsLayer.cpp @@ -0,0 +1,29 @@ +#include +#include +#include + +class $modify(LeaderboardsLayer) { + bool init(LeaderboardType type, LeaderboardStat stat) { + if (!LeaderboardsLayer::init(type, stat)) return false; + + auto menu = CCMenu::create(); + + Build::createSpriteName("GJ_plusBtn_001.png").scale(.8f) + .intoMenuItem([]() { + auto scene = CCScene::create(); + scene->addChild(MoreLeaderboards::create("more")); + CCDirector::sharedDirector()->pushScene(CCTransitionFade::create(0.5, scene)); + }).pos(-239, 20).id("more-leaderboards-btn"_spr).parent(menu); + + Build::createSpriteName("modBadge_01_001.png").scale(1.5f) + .intoMenuItem([]() { + auto scene = CCScene::create(); + scene->addChild(MoreLeaderboards::create("mods")); + CCDirector::sharedDirector()->pushScene(CCTransitionFade::create(0.5, scene)); + }).pos(-239, -24).id("mods-list-btn"_spr).parent(menu); + + menu->setID("gdutils-menu"_spr); + this->addChild(menu); + return true; + } +}; diff --git a/src/hooks/LevelInfoLayer.cpp b/src/hooks/LevelInfoLayer.cpp new file mode 100644 index 0000000..edf0cc7 --- /dev/null +++ b/src/hooks/LevelInfoLayer.cpp @@ -0,0 +1,175 @@ +#include +#include +#include +#include + +// demon list +std::unordered_map demonListCache; // Will clear after game exit, or if user deletes level + +class $modify(CustomLevelInfoLayer, LevelInfoLayer) { + struct Fields { + async::TaskHolder m_listener; + }; + void set(int key, int value) { + demonListCache[key] = value; + } + bool exists(int key) { + return demonListCache.find(key) != demonListCache.end(); + } + int get(int key) { + auto it = demonListCache.find(key); + if (it != demonListCache.end()) { + return it->second; + } + return -1; + } + bool remove(int key) { + return demonListCache.erase(key) == 1; + } + float getScaleBasedPos(int pos) { + if (pos > 0 && pos < 10) return 0.5F; + if (pos > 10 && pos < 100) return 0.4F; + if (pos > 100 && pos < 1000) return 0.3F; + if (pos > 1000 && pos < 10000) return 0.2F; + return 0.1F; + } + bool init(GJGameLevel* level, bool p1) { // inspiration le gdbrowser, what does p1 do? idk + if (!LevelInfoLayer::init(level, p1)) return false; + if (level->m_demon.value() == 0 || level->m_stars.value() != 10) return true; + if (level->m_demonDifficulty != 6) return true; + + auto director = CCDirector::sharedDirector(); + auto winSize = director->getWinSize(); + auto demonSpr = Build::createSpriteName("diffIcon_06_btn_001.png") + .pos({ + (winSize.width / 2) - 85, + (level->m_coins > 0) ? (winSize.height / 2) : (winSize.height / 2) + 18 + }) + .scale(0.5F) + .id("demon-spr"_spr) + .visible(false) + .parent(this) + .collect(); + auto positionLabel = Build::create("N/A", "bigFont.fnt") + .pos({ + (winSize.width / 2) - 107, + (level->m_coins > 0) ? (winSize.height / 2) : (winSize.height / 2) + 18 + }) + .scale(0.5F) + .id("demon-pos"_spr) + .visible(false) + .parent(this) + .collect(); + int levelID = level->m_levelID.value(); + if (exists(levelID)) { + int position = get(levelID); + if (position > 0) { + positionLabel->setString(fmt::format("#{}", position).c_str()); + positionLabel->setScale(getScaleBasedPos(position)); + positionLabel->setVisible(true); + demonSpr->setVisible(true); + } + } else { + auto loading_circle = LoadingCircle::create(); + if (level->m_coins > 0) { + loading_circle->setPosition({-100, -2}); + loading_circle->setScale(0.3F); + } else { + loading_circle->setPosition({-100, 8}); + loading_circle->setScale(0.4F); + } + loading_circle->setParentLayer(this); + loading_circle->show(); + std::string listId = Mod::get()->getSettingValue("demonListSelection"); + std::string url = ""; + if (listId == "Pointercrate") { + url = fmt::format("https://pointercrate.com/api/v2/demons/listed/?level_id={}", levelID); + } else { + url = fmt::format("https://api.aredl.net/v2/api/aredl/levels/{}", levelID); + } + geode::utils::web::WebRequest request = web::WebRequest(); + m_fields->m_listener.spawn("@loaderDemonListLevelInfo", request.get(url.c_str()), [this, loading_circle, positionLabel, demonSpr, levelID](web::WebResponse value) { + if (value.ok()) { + matjson::Value json = value.json().unwrapOrDefault(); + + std::string listId = Mod::get()->template getSettingValue("demonListSelection"); + + if (listId == "Pointercrate") { + if (loading_circle != nullptr) { + loading_circle->fadeAndRemove(); + } + auto scene = CCDirector::sharedDirector()->getRunningScene(); + if (json.dump() == "[]") { //idk how to check size, doing .count crashes + log::info("Level not found in Pointercrate."); + } else { + auto info = json.get(0); + if (info.isOk()) { + auto positionRes = info.unwrap().get("position"); + if (positionRes.isOk()) { + int position = positionRes.unwrap().asInt().unwrapOrDefault(); + positionLabel->setString(fmt::format("#{}", position).c_str()); + positionLabel->setScale(getScaleBasedPos(position)); + positionLabel->setVisible(true); + demonSpr->setVisible(true); + set(levelID, position); + log::info("Level found in Pointercrate! {} at #{}", levelID, position); + } + } + + } + } else { + if (loading_circle != nullptr) { + loading_circle->fadeAndRemove(); + } + auto scene = CCDirector::sharedDirector()->getRunningScene(); + if (json.contains("code")) { + } else { + auto positionRes = json.get("position"); + if (positionRes.isOk()) { + int position = positionRes.unwrap().asInt().unwrapOrDefault(); + positionLabel->setString(fmt::format("#{}", position).c_str()); + positionLabel->setScale(getScaleBasedPos(position)); + positionLabel->setVisible(true); + demonSpr->setVisible(true); + set(levelID, position); + log::info("Level found in AREDL! {} at #{}", levelID, position); + } + } + } + } else { + if (loading_circle != nullptr) { + loading_circle->fadeAndRemove(); + } + log::error("Error while sending a request to Demon List: {}", value.errorMessage()); + } + }); + } + return true; + } +}; +// demon list + +static void toggleHook(bool value) { + for (auto& hook : geode::Mod::get()->getHooks()) { + if (hook->getDisplayName() == "LevelInfoLayer::init") { + if (value) { + (void)hook->enable(); + } else { + (void)hook->disable(); + } + } + } +} + +$execute { + listenForSettingChanges("demonListPlacement", [](bool value) { + log::info("Demon List Placement changed to {}", value); + toggleHook(value); + }); +} + +$on_mod(Loaded) { + if (!Mod::get()->getSettingValue("demonListPlacement")) { + toggleHook(false); + } +} diff --git a/src/hooks/SecretLayer.cpp b/src/hooks/SecretLayer.cpp new file mode 100644 index 0000000..0f6586e --- /dev/null +++ b/src/hooks/SecretLayer.cpp @@ -0,0 +1,44 @@ +#include +#include + +class $modify(SecretLayer) { + bool init() { + if (!SecretLayer::init()) return false; + auto winSize = CCDirector::sharedDirector()->getWinSize(); + auto bg = CCSprite::createWithSpriteFrameName("thevault.png"_spr); + bg->setPosition(winSize / 2); + bg->setZOrder(-1); + bg->setScaleY(winSize.height / bg->getContentSize().height); + bg->setScaleX(winSize.width / bg->getContentSize().width); + this->addChild(bg); + if (auto vaultName = this->getChildByID("vault-name")) { + vaultName->setVisible(false); + } + return true; + } +}; + +static void toggleHook(bool value) { + for (auto& hook : geode::Mod::get()->getHooks()) { + if (hook->getDisplayName() == "SecretLayer::init") { + if (value) { + (void)hook->enable(); + } else { + (void)hook->disable(); + } + } + } +} + +$execute { + listenForSettingChanges("secretLayerDesign", [](bool value) { + log::info("SecretLayer Design changed to {}", value); + toggleHook(value); + }); +} + +$on_mod(Loaded) { + if (!Mod::get()->getSettingValue("secretLayerDesign")) { + toggleHook(false); + } +} diff --git a/src/Secret/BadApple.cpp b/src/hooks/SecretLayer2.cpp similarity index 55% rename from src/Secret/BadApple.cpp rename to src/hooks/SecretLayer2.cpp index 3297a51..0d646a5 100644 --- a/src/Secret/BadApple.cpp +++ b/src/hooks/SecretLayer2.cpp @@ -1,99 +1,42 @@ -// SPOILERSSS -#include "BadApple.h" -#ifdef GEODE_IS_WINDOWS -#include "../Utils/DownloadManager.h" -#else // mac -#include -#include -#endif -BadApple* BadApple::create() { - auto pRet = new BadApple(); - if (pRet && pRet->BadApple::init()) { - pRet->autorelease(); - return pRet; - } - CC_SAFE_DELETE(pRet); - return nullptr; -}; - -bool BadApple::init() { - auto menu = CCMenu::create(); - //#ifndef GEODE_IS_MACOS - #ifdef GEODE_IS_WINDOWS - videoplayer::VideoPlayer* player = videoplayer::VideoPlayer::create("./gdutils/bad_apple.mpg", true); - CCDirector* director = CCDirector::sharedDirector(); - CCSize size = director->getWinSize(); - player->setPosition(size.width / 2, size.height / 2); - player->setContentSize({ size.width - 40, size.height - 40 }); - player->setZOrder(-1); - this->addChild(player); - #endif - setKeypadEnabled(true); - - return true; -} - -void BadApple::keyBackClicked() { - setKeypadEnabled(false); - - #ifdef GEODE_IS_UNKNOWN - GameSoundManager::sharedManager()->playBackgroundMusic("./Resources/secretLoop02.mp3", true, false); - #endif - CCDirector::sharedDirector()->popSceneWithTransition(0.5f, PopTransition::kPopTransitionFade); -} - // touhou time -//#ifdef GEODE_IS_WINDOWS -std::string text_input = ""; -#include "BadApple.h" -bool bad_apple = false; -#include "COTE.h" -bool cote = false; - #include +#include +#include +#include +#include + +enum States { + None, + BadApple, + COTE +}; class $modify(SecretVault, SecretLayer2) { struct Fields { CCMenu* m_menu = nullptr; + States m_currentState = States::None; }; bool init() { if (!SecretLayer2::init()) return false; - bad_apple = false; - cote = false; return true; } void onSubmit(CCObject* obj) { + gd::string input = m_searchInput->getString(); SecretLayer2::onSubmit(obj); - if (m_fields->m_menu == nullptr) { - m_fields->m_menu = CCMenu::create(); - m_fields->m_menu->setPosition(50, 200); - m_fields->m_menu->setContentSize({ 100, 200 }); - m_fields->m_menu->setLayout( - ColumnLayout::create() - ->setCrossAxisAlignment(AxisAlignment::Center) - ); + Build::create().pos(50, 200).contentSize({100, 200}).layout( + ColumnLayout::create()->setCrossAxisAlignment(AxisAlignment::Center) + ).store(m_fields->m_menu).parent(this); } - - this->addChild(m_fields->m_menu); - m_fields->m_menu->removeAllChildren(); - - CCLabelBMFont* vault_text = nullptr; - if (this->getChildByIDRecursive("vault-text") == nullptr) { - vault_text = typeinfo_cast(this->getChildren()->objectAtIndex(3)); - } else { - vault_text = as(this->getChildByIDRecursive("vault-text")); - vault_text->setID("vault-text"); + CCLabelBMFont* vault_text = typeinfo_cast(this->getChildByIDRecursive("vault-text")); + if (!vault_text) { + vault_text = this->getChildByType(1); } - - if (!strcmp(text_input.c_str(), "bad apple")) { - if (!bad_apple) { - std::filesystem::create_directory("gdutils"); - bad_apple = true; - cote = false; - + if (!strcmp(input.c_str(), "bad apple")) { + if (m_fields->m_currentState != States::BadApple) { + m_fields->m_currentState = States::BadApple; auto menu = CCMenu::create(); menu->setLayout( RowLayout::create() @@ -127,12 +70,9 @@ class $modify(SecretVault, SecretLayer2) { menu->updateLayout(); m_fields->m_menu->addChild(menu); } - } else if (!strcmp(text_input.c_str(), "honami best girl")) { - if (!cote) { - std::filesystem::create_directory("gdutils"); - cote = true; - bad_apple = false; - + } else if (!strcmp(input.c_str(), "honami best girl")) { + if (m_fields->m_currentState != States::COTE) { + m_fields->m_currentState = States::COTE; auto menu = CCMenu::create(); menu->setLayout( RowLayout::create() @@ -167,15 +107,12 @@ class $modify(SecretVault, SecretLayer2) { m_fields->m_menu->addChild(menu); } } else { - cote = false; - bad_apple = false; + m_fields->m_currentState = States::None; } - m_fields->m_menu->updateLayout(); } - void launchBadApple(CCObject* pSender) { - + void launchBadApple() { //GameSoundManager::sharedManager()->stopBackgroundMusic(); FMODAudioEngine::sharedEngine()->stopAllMusic(true); auto scene = cocos2d::CCScene::create(); @@ -185,19 +122,19 @@ class $modify(SecretVault, SecretLayer2) { } void onLaunchBadApple(CCObject* pSender) { - if (std::filesystem::exists("gdutils/bad_apple.mpg")) { - auto node = CCNode::create(); - node->setTag(10); - SecretVault::launchBadApple(node); + if (std::filesystem::exists(Mod::get()->getSaveDir() / "bad_apple.mpg")) { + SecretVault::launchBadApple(); } else { log::info("wait for bad apple"); #ifdef GEODE_IS_WINDOWS - DownloadManager::create("https://clarifygdps.com/videos/bad_apple.mpg", "gdutils/bad_apple.mpg", menu_selector(SecretVault::launchBadApple))->show(); + DownloadPopup::create("https://clarifygdps.com/videos/bad_apple.mpg", Mod::get()->getSaveDir() / "bad_apple.mpg", [this]() { + SecretVault::launchBadApple(); + })->show(); #endif } } - void launchCOTE(CCObject* pSender) { + void launchCOTE() { //GameSoundManager::sharedManager()->stopBackgroundMusic(); FMODAudioEngine::sharedEngine()->stopAllMusic(true); auto scene = cocos2d::CCScene::create(); @@ -207,23 +144,20 @@ class $modify(SecretVault, SecretLayer2) { } void onLaunchCOTE(CCObject* pSender) { - if (std::filesystem::exists("gdutils/cote.mpg")) { - auto node = CCNode::create(); - node->setTag(10); - SecretVault::launchCOTE(node); + if (std::filesystem::exists(Mod::get()->getSaveDir() / "cote.mpg")) { + SecretVault::launchCOTE(); } else { log::info("wait for cote"); #ifdef GEODE_IS_WINDOWS - DownloadManager::create("https://clarifygdps.com/videos/cote.mpg", "gdutils/cote.mpg", menu_selector(SecretVault::launchCOTE))->show(); + DownloadPopup::create("https://clarifygdps.com/videos/cote.mpg", Mod::get()->getSaveDir() / "cote.mpg", [this]() { + SecretVault::launchCOTE(); + })->show(); #endif } + } void updateSearchLabel(const char* text) { - if (strlen(text) > 0) { - text_input = text; - } SecretLayer2::updateSearchLabel(text); } }; -// touhou time diff --git a/src/includes.h b/src/includes.h deleted file mode 100644 index 8c467a4..0000000 --- a/src/includes.h +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once -#include -#include -using namespace geode::prelude; - -#include -#include -#include -#include - -#define OPT(expr) if (auto __opt__ = expr) __opt__ - -class misc { - public: - // theres no including Geode Util class funcs so, https://github.com/geode-sdk/DevTools - static std::string getNodeName(cocos2d::CCObject* node) { -#ifdef GEODE_IS_WINDOWS - return typeid(*node).name() + 6; -#else - { - std::string ret; - - int status = 0; - auto demangle = abi::__cxa_demangle(typeid(*node).name(), 0, 0, &status); - if (status == 0) { - ret = demangle; - } - free(demangle); - - return ret; - } -#endif - } - static CCObject* findNode(std::string name) { - auto scene = CCDirector::sharedDirector()->getRunningScene(); - auto sceneChildren = scene->getChildren(); - for (unsigned int i = 0; i < scene->getChildrenCount(); i++) { - auto node = sceneChildren->objectAtIndex(i); - if (node != nullptr) { - std::string layerName = misc::getNodeName(node); - std::cout << layerName << std::endl; - if (layerName == name) { - return node; - } - } - } - return nullptr; - } - template - static std::vector> paginate(const std::vector& arr, size_t size) { - std::vector> paginated; - for (size_t i = 0; i < arr.size(); i += size) { - std::vector page; - for (size_t j = i; j < std::min(i + size, arr.size()); ++j) { - page.push_back(arr[j]); - } - paginated.push_back(page); - } - return paginated; - } - - static std::string genClientID() { - // this is just for statistics ok - #ifdef GEODE_IS_WINDOWS - std::string platform = "Windows"; - #elif defined(GEODE_IS_ANDROID) - std::string platform = "Android"; - #elif defined(GEODE_IS_MACOS) - std::string platform = "Mac"; - #elif defined(GEODE_IS_IOS) - std::string platform = "iOS"; - #else - std::string platform = "Unknown"; - #endif - - const std::string charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> dist(0, charset.size() - 1); - - std::string randomStr; - for (size_t i = 0; i < 8; ++i) { - randomStr.push_back(charset[dist(gen)]); - } - - auto now = std::chrono::system_clock::now(); - auto now_ms = std::chrono::duration_cast(now.time_since_epoch()).count(); - int accountID = 0; - if (auto gjam = GJAccountManager::get()) { - accountID = gjam->m_accountID; - } - return fmt::format("gdutils-{}-{}-{}-{}", accountID, platform, now_ms, randomStr); - } -}; diff --git a/src/main.cpp b/src/main.cpp index 8a94aab..94287a5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,850 +2,127 @@ // Ported with help by Firee // Mod made by Jouca & Firee -#include -#include -#include +//#include "defs/FileWatcher.hpp" +#include "modules/events/DailyChest.hpp" +$execute { + // listenForSettingChanges("activate-background", [](bool value) { + // log::info("Activate Background changed to {}", value); + // toggleSpriteHooks(value); + // }); +} +#include +#include #include -#include -#include -#include "includes.h" -#include "Settings/CustomSettings.hpp" -#include "Notifications/EventsPush.h" -#include "ProcessLambdas.h" -#include -#include -#include -#include #include -#include -#include -#include -#include -#include "Notifications/DailyChest.h" -#include - -bool show_connected = false; - -#ifdef GEODE_IS_WINDOWS // stop the dumb compiler errors! -#include -#include -//#include -#endif - -//#include -//#include -//#include - -// ah yes, lets use the raw version of the library instead of the c++ one because IT DOESNT IMPLEMENT SOCKETS -#include -#include - -//#include - -std::queue dataQueue; -std::queue chestQueue; - -std::queue msgQueue; - -std::string AMQReplyToString(amqp_response_type_enum val) { - switch (val) { - case AMQP_RESPONSE_NONE: - default: - return "AMQP_RESPONSE_NONE"; - case AMQP_RESPONSE_NORMAL: - return "AMQP_RESPONSE_NORMAL"; - case AMQP_RESPONSE_LIBRARY_EXCEPTION: - return "AMQP_RESPONSE_LIBRARY_EXCEPTION"; - case AMQP_RESPONSE_SERVER_EXCEPTION: - return "AMQP_RESPONSE_SERVER_EXCEPTION"; - } -} -std::string AMQErrorToString(amqp_rpc_reply_t reply) { - std::string errorStr; - switch (reply.reply_type) { - case AMQP_RESPONSE_NONE: errorStr = "No response"; break; - case AMQP_RESPONSE_LIBRARY_EXCEPTION: errorStr = amqp_error_string2(reply.library_error); break; - case AMQP_RESPONSE_SERVER_EXCEPTION: - if (reply.reply.id == AMQP_CONNECTION_CLOSE_METHOD) { - amqp_connection_close_t* m = (amqp_connection_close_t*) reply.reply.decoded; - errorStr = (char*)m->reply_text.bytes; - } else { - errorStr = "Unknown Error"; - } - break; - } - return fmt::format("{} ({})", errorStr, AMQReplyToString(reply.reply_type)); -} - -#define MAX_RECONNECT_ATTEMPTS 20 - -class AMQT { - private: - amqp_connection_state_t m_connection; - //std::unique_ptr m_socket; - amqp_socket_t* m_socket; - std::string client_id; - - std::atomic m_remainingAttempts = {MAX_RECONNECT_ATTEMPTS}; - std::atomic m_connected{false}; - - std::mutex m_mutex; - std::condition_variable m_cv; - - std::chrono::steady_clock::time_point m_lastActivityTime; - std::chrono::steady_clock::time_point m_lastHeartbeatTime; - - public: - AMQT(const std::string& client_id) : client_id(client_id) { - m_lastActivityTime = std::chrono::steady_clock::now(); - m_lastHeartbeatTime = m_lastActivityTime; - }; - void updateActivity() { - m_lastActivityTime = std::chrono::steady_clock::now(); - } - // since the current heartbeat does NOT work!! - bool sendHeartbeat() { - auto now = std::chrono::steady_clock::now(); - auto lastDuration = std::chrono::duration_cast(now - m_lastHeartbeatTime).count(); - // every 10 seconds - if (lastDuration >= 10) { - std::lock_guard lock(m_mutex); - if (isConnected()) { - // because WHY CANT I USE amqp_heartbeat_send!?!? we will decide to manually construct it... - amqp_frame_t frame; - frame.channel = 0; // or 1? idk... amqp_socket.c says 0 - frame.frame_type = AMQP_FRAME_HEARTBEAT; - auto res = amqp_send_frame(m_connection, &frame); - if (AMQP_STATUS_OK != res) { - log::warn("Failed to send heartbeat: {}", amqp_error_string2(res)); - return false; - } else { - //log::debug("Sent heartbeat!"); - m_lastHeartbeatTime = now; - return true; - } - } - } - return true; - } - bool isConnected() { - return m_connected.load(); - } - void setupChannel() { - //bool showPastNotifs = Mod::get()->template getSettingValue("past-notifications"); - bool showPastNotifs = false; - std::string queueName = fmt::format("amqp-queue-{}", client_id); - { - amqp_channel_open(m_connection, 1); - auto reply = amqp_get_rpc_reply(m_connection); - if (reply.reply_type != AMQP_RESPONSE_NORMAL) { - log::error("Error opening channel: {}", AMQErrorToString(reply)); - return; - } - } - // https://stackoverflow.com/questions/72237234/declare-a-queue-with-x-max-length-programmatically-using-rabbitmq-c - amqp_queue_declare_ok_t *r; - if (showPastNotifs) { - // this is absolutely cursed - /*amqp_table_entry_t q_arg_n_entries[2]; - q_arg_n_entries[0] = (amqp_table_entry_t) { - .key = amqp_cstring_bytes("x-queue-type"), - .value = {.kind = AMQP_FIELD_KIND_UTF8, .value = {.bytes = amqp_cstring_bytes("classic")}} - }; - - //86400000 - // 2 days - q_arg_n_entries[1] = (amqp_table_entry_t) { - .key = amqp_cstring_bytes("x-expires"), - .value = {.kind = AMQP_FIELD_KIND_I32, .value = {.i32 = 172800000}} - }; - amqp_table_t q_arg_table = {.num_entries = 2, .entries = q_arg_n_entries};*/ - - amqp_table_entry_t q_arg_n_entries[1]; - // 1 day - q_arg_n_entries[0] = (amqp_table_entry_t) { - .key = amqp_cstring_bytes("x-expires"), - .value = {.kind = AMQP_FIELD_KIND_I32, .value = {.i32 = 86400000}} - }; - amqp_table_t q_arg_table = {.num_entries = 1, .entries = q_arg_n_entries}; - r = amqp_queue_declare( - m_connection, 1, - amqp_cstring_bytes(queueName.c_str()), - 0, 1, 0, 0, - q_arg_table - ); - } else { - amqp_queue_delete(m_connection, 1, amqp_cstring_bytes(queueName.c_str()), 0, 0); - amqp_get_rpc_reply(m_connection); - r = amqp_queue_declare( - m_connection, 1, - amqp_cstring_bytes(queueName.c_str()), - 0, 0, 0, 1, - amqp_empty_table - ); - } - { - auto reply = amqp_get_rpc_reply(m_connection); - if (reply.reply_type != AMQP_RESPONSE_NORMAL) { - log::error("Error declaring queue: {}", AMQErrorToString(reply)); - return; - } - } - amqp_bytes_t queueBytes = amqp_bytes_malloc_dup(r->queue); - if (queueBytes.bytes == NULL) { - log::error("Couldn't copy queue name (Out of memory?)"); - return; - } - { - amqp_queue_bind(m_connection, 1, - queueBytes, amqp_cstring_bytes("amq.topic"), - amqp_cstring_bytes("rate.#"), amqp_empty_table - ); - auto reply = amqp_get_rpc_reply(m_connection); - if (reply.reply_type != AMQP_RESPONSE_NORMAL) { - log::error("Error binding queue: {}", AMQErrorToString(reply)); - return; - } - } - { - auto res = amqp_basic_consume(m_connection, 1, queueBytes, amqp_empty_bytes, 0, 1, 0, amqp_empty_table); - auto reply = amqp_get_rpc_reply(m_connection); - - if (reply.reply_type != AMQP_RESPONSE_NORMAL) { - log::error("Error consuming in queue: {}", AMQErrorToString(reply)); - return; - } - if (res) { - std::string data((char*)res->consumer_tag.bytes, res->consumer_tag.len); - show_connected = true; - log::info("Subscribed to Rate Notifications! (Consumer Tag: {})", data); - } - } +#include +#include +#include +#include - bool forceReconnection = false; - auto lastReconnectTime = std::chrono::steady_clock::now(); +static bool g_socket_server_ran = false; +//static FileWatcher* g_watcher; - struct timeval timeout = {10, 0}; - - while (isConnected()) { - // this is just an extra so we're sure that we're always connected - if (!sendHeartbeat()) { - log::error("Couldn't send heartbeat, disconnecting..."); - break; - } - - if (forceReconnection) { - auto now = std::chrono::steady_clock::now(); - auto lastDuration = std::chrono::duration_cast(now - lastReconnectTime).count(); - if (lastDuration >= 600) { - log::info("Forcing a reconnection..."); - break; - } - } - - amqp_envelope_t envelope; - amqp_maybe_release_buffers(m_connection); - - auto ret = amqp_consume_message(m_connection, &envelope, &timeout, 0); - if (AMQP_RESPONSE_NORMAL != ret.reply_type) { - if (AMQP_RESPONSE_LIBRARY_EXCEPTION == ret.reply_type && AMQP_STATUS_HEARTBEAT_TIMEOUT == ret.library_error) { - log::error("Heartbeat failed, initiating a reconnection!"); - break; - } else if (AMQP_RESPONSE_LIBRARY_EXCEPTION == ret.reply_type && AMQP_STATUS_UNEXPECTED_STATE == ret.library_error) { - amqp_frame_t frame; - if (AMQP_STATUS_OK != amqp_simple_wait_frame(m_connection, &frame)) { - log::error("Failed to wait for frame after unexpected state: {}", AMQErrorToString(ret)); - break; - } - if (AMQP_FRAME_METHOD == frame.frame_type) { - if (frame.payload.method.id == AMQP_BASIC_ACK_METHOD) continue; - if (frame.payload.method.id == AMQP_BASIC_RETURN_METHOD) { - { - log::info("Got frame payload, re-reading message based on channel..."); - amqp_message_t message; - ret = amqp_read_message(m_connection, frame.channel, &message, 0); - if (AMQP_RESPONSE_NORMAL != ret.reply_type) { - log::error("Error reading returned message: {}", AMQErrorToString(ret)); - break; - } - std::string data((char*)message.body.bytes, message.body.len); - msgQueue.push(data); - amqp_destroy_message(&message); - } - continue; - } else { - log::error("(Frame ID: {}) Error consuming message: {}", frame.payload.method.id, AMQErrorToString(ret)); - break; - } - } else { - log::error("Response wasn't normal! {}", AMQErrorToString(ret)); - } - } else if (AMQP_RESPONSE_LIBRARY_EXCEPTION == ret.reply_type && AMQP_STATUS_TIMEOUT == ret.library_error) { - // honestly how has no one gotten this issue!? - continue; - } else { - log::error("Error consuming message: {}", AMQErrorToString(ret)); - break; - } - } else { - log::info("call rate event"); - std::string data((char*)envelope.message.body.bytes, envelope.message.body.len); - msgQueue.push(data); - amqp_destroy_envelope(&envelope); - } - } - m_connected = false; - m_cv.notify_all(); - } - void connect() { - m_remainingAttempts++; - while (m_remainingAttempts-- > 0) { - log::info("Starting AMQP..."); - if (m_remainingAttempts != MAX_RECONNECT_ATTEMPTS) { - int currentAttempt = MAX_RECONNECT_ATTEMPTS - m_remainingAttempts + 1; - int delayMs = 3000 * std::pow(2, currentAttempt - 1); - //TODO: fix it being stuck on 3 seconds - log::warn("Disconnected from server. Attempting to reconnect... ({} left, reconnecting in {} seconds)", m_remainingAttempts, (float)((delayMs / 1000.F))); - std::this_thread::sleep_for(std::chrono::milliseconds(delayMs)); - } - m_connection = amqp_new_connection(); - amqp_socket_t* socket = amqp_tcp_socket_new(m_connection); - if (!socket) { - log::error("Couldn't create TCP connection"); - continue; - } - int status; - status = amqp_socket_open(socket, "gdutils.clarifygdps.com", 5672); - if (status != AMQP_STATUS_OK) { - log::error("Error opening socket! {}", amqp_error_string2(status)); - continue; - } - if (socket && m_connection) { - // heartbeat every 10 seconds! - amqp_rpc_reply_t reply = amqp_login(m_connection, "/", 0, 131072, 10, AMQP_SASL_METHOD_PLAIN, "gd", "GeometryDashisahorizontalrunnerstylegamedevelopedandpublishedbyRobTopGames"); - if (reply.reply_type != AMQP_RESPONSE_NORMAL) { - const char* errorStr = nullptr; - log::error("Couldn't login to AMQP server! {}", AMQErrorToString(reply)); - continue; - } - m_connected = true; - setupChannel(); - /* - std::unique_lock lock(m_mutex); - if (!m_cv.wait_for(lock, std::chrono::seconds(10), [this]{ - return m_connection; // change thispls - })) { - log::error("Connection timeout, assuming I can't connect!"); - } - while (isConnected()) { - m_cv.wait_for(lock, std::chrono::seconds(1), [this] { return !isConnected(); }); - }*/ - //amqp_connection_close(m_connection, AMQP_REPLY_SUCCESS); - disconnect(); - } - } - log::error("Maximum reconnection attempts reached, cannot reconnect. Restart the game to reconnect to the MQTT server."); - } - void disconnect() { - if (m_connection) { - m_connected = false; - amqp_destroy_connection(m_connection); - m_connection = nullptr; - } - } -}; - -static std::unordered_map RUNNING_REQUESTS {}; -static std::mutex lock_var; - -std::string xorEncrypt(const std::string& input, const std::string& key) { - std::string result; - for (size_t i = 0; i < input.size(); ++i) { - result += input[i] ^ key[i % key.size()]; - } - return result; -} - -// Daily chests notifications -/*void dailyChestThread() { - while (true) { - chestQueue.push(1); - std::this_thread::sleep_for(std::chrono::minutes(1)); - } -}*/ - -void processEvent(CCScene* self) { - if (!dataQueue.empty()) { - auto data = dataQueue.front(); - dataQueue.pop(); - EventsPush::pushRateLevel(self, data); - } -} - -void processChestEvent(CCScene* self) { - if (!chestQueue.empty()) { - auto data = chestQueue.front(); - chestQueue.pop(); - auto dailyChest = new DailyChest(); - dailyChest->getRewards(0); - } -} - -class EventHandler : public CCObject { - protected: - std::string m_currentLayer; - public: - static EventHandler* create() { - auto pRet = new EventHandler(); - if (pRet) { - pRet->autorelease(); - return pRet; - } - CC_SAFE_DELETE(pRet); - return nullptr; - } - void checkForEvent() { - auto director = CCDirector::sharedDirector(); - if (!director) return; - bool waitUntilExit = false; - auto scene = CCDirector::sharedDirector()->getRunningScene(); - if (!scene) return; - if (scene->getChildrenCount() == 0) return; - if (show_connected) { - show_connected = false; - if (Mod::get()->template getSettingValue("server-notification")) { +$execute { + if (Mod::get()->getSettingValue("server-notification")) { + GDUtils::Events::OnServerConnect().listen([](bool const& connected) { + Loader::get()->queueInMainThread([connected]() { + if (connected) { Notification::create("Connected to Rate Server!", NotificationIcon::Success)->show(); } - } - auto layer = scene->getChildren()->objectAtIndex(0); - if (ProcessLambdas::shouldProcessMenuHandler()) { - ProcessLambdas::processMenuHandler(); - } - std::string layerName = misc::getNodeName(layer); - if (layerName == "cocos2d::CCLayerColor") return; - if (layerName == "LoadingLayer") return; - if (m_currentLayer != layerName) { - m_currentLayer = layerName; - EventsPush::stopNow(scene); - bool everywhereElse = Mod::get()->template getSettingValue("everywhereElse"); - if ((layerName != "LevelEditorLayer" && layerName != "PlayLayer") && !everywhereElse) return; - if ((layerName != "LevelEditorLayer" && layerName != "PlayLayer") && everywhereElse) { - processChestEvent(scene); - processEvent(scene); - } - } - if (msgQueue.empty()) return; - bool everywhereElse = Mod::get()->template getSettingValue("everywhereElse"); - bool inLevels = Mod::get()->template getSettingValue("inLevels"); - bool inEditor = Mod::get()->template getSettingValue("inEditor"); - bool inPlatformers = Mod::get()->template getSettingValue("inPlatformers"); - - bool pushEvent = true; - if (layerName == "PlayLayer") { - if (!inLevels) pushEvent = false; - - PlayLayer* playLayer = reinterpret_cast(layer); - GJGameLevel* level = playLayer->m_level; - if (level->isPlatformer() && !inPlatformers) { - pushEvent = false; - } - } - if (layerName == "LevelEditorLayer" && !inEditor) { - pushEvent = false; - } - if ((layerName != "LevelEditorLayer" && layerName != "PlayLayer") && !everywhereElse) { - pushEvent = false; - } - dataQueue.push(msgQueue.front()); - msgQueue.pop(); - if (pushEvent) processEvent(scene); - } - void checkForFiles() { - #ifdef GEODE_IS_WINDOWS - auto scene = CCDirector::sharedDirector()->getRunningScene(); - if (!scene) return; - if (scene->getChildrenCount() == 0) return; - auto layer = scene->getChildren()->objectAtIndex(0); - if (layer == nullptr) return; - std::string layerName = misc::getNodeName(layer); - if (layerName == "cocos2d::CCLayerColor") return; - if (layerName == "LoadingLayer") return; - if (layerName == "LevelEditorLayer") return; - if (layerName == "PlayLayer") return; - if (layerName == "LoadingLayer") return; - bool levelsProtocol = Mod::get()->template getSettingValue("levelsProtocol"); - if (!levelsProtocol) return; - auto glm = GameLevelManager::sharedState(); - try { - for (const auto & entry : std::filesystem::directory_iterator("gdutils")) { - if (entry.path().extension() == ".flag") { - std::string path = entry.path().string(); - std::string filename = entry.path().filename().string(); - std::string levelName = filename.substr(0, filename.length() - 5); - - try { - std::filesystem::remove("gdutils/" + filename); - } catch (const std::exception& e) { - break; - } - - std::string url = "https://www.boomlings.com/database/getGJLevels21.php"; - std::string fields = fmt::format("secret=Wmfd2893gb7&type=0&str={}", levelName); - - geode::utils::web::WebRequest request = web::WebRequest(); - request.userAgent(""); - request.header("Content-Type", "application/x-www-form-urlencoded"); - const std::lock_guard lock(lock_var); - RUNNING_REQUESTS.emplace( - "@loaderLevelProtocolURL", - request.bodyString(fields).post(url).map( - [](web::WebResponse* response) { - const std::lock_guard lock(lock_var); - if (response->ok()) { - if (response->data().empty()) { - FLAlertLayer::create(nullptr, - "Error (GDUtils)", - "An error has occured with Robtop's servers. The response returned empty.", - "OK", - nullptr, - 180.0F - )->show(); - } else { - auto data = response->string().unwrapOrDefault(); - if (data != "-1") { - auto scene = CCScene::create(); - - GJGameLevel* gjgl = EventsPush::convertLevelToJSON(data); - - auto layer = LevelInfoLayer::create(gjgl, false); - layer->downloadLevel(); - scene->addChild(layer); - CCDirector::sharedDirector()->pushScene(cocos2d::CCTransitionFade::create(0.5f, scene)); - } else { - FLAlertLayer::create(nullptr, - "Error", - "Level not found.", - "OK", - nullptr, - 180.0F - )->show(); - } - } - } else { - FLAlertLayer::create(nullptr, - "Error (GDUtils)", - "An error has occured with Robtop's servers. The reason could be because you are either ratelimited, blocked, or another issue.", - "OK", - nullptr, - 180.0F - )->show(); - } - - RUNNING_REQUESTS.erase("@loaderLevelProtocolURL"); - return *response; - } - ) - ); + }); + return ListenerResult::Stop; + }).leak(); + } + auto [tx, rx] = arc::mpsc::channel(1024); // i mean why would robtop ever rate that many levels + auto [etx, erx] = arc::mpsc::channel(1024); // ditto + auto [ctx, crx] = arc::mpsc::channel(64); + AMQT::setTx(std::move(tx)); + EventsPush::setTx(std::move(ctx)); + //auto interval = arc::interval(Duration::fromMillis(250)); + async::runtime().spawn([rx = std::move(rx), crx = std::move(crx), erx = std::move(erx)]() mutable -> arc::Future<> { + bool running = true; + while (running) { + co_await arc::select( + arc::selectee(rx.recv(), [&](auto req) { + if (req) { + std::string msg = std::move(req).unwrap(); + Loader::get()->queueInMainThread([m = std::move(msg)]() mutable { + auto director = CCDirector::sharedDirector(); + if (!director) return; + auto scene = CCDirector::sharedDirector()->getRunningScene(); + if (!scene) return; + if (scene->getChildrenCount() == 0) return; + if (EventsPush::canSendEvent(scene)) { + EventsPush::pushRateLevel(scene, m); + } + }); } - } - } catch (const std::exception& e) {} - #endif - } - void check(float dt) { - checkForEvent(); - checkForFiles(); - } -}; - -// Backgrounds -// i dont like ios -#ifndef GEODE_IS_IOS -class $modify(UtilCCSprite, CCSprite) { - static CCSprite* create(char const* name) { - auto ret = CCSprite::create(name); - if (ret == nullptr) return ret; - // better code, thanks camila! - if (!strcmp(name, "GJ_gradientBG.png") && Mod::get()->template getSettingValue("activate-background")) { - ret->retain(); - Loader::get()->queueInMainThread([=] { - if (ret != nullptr) { - if (ret->getColor() == ccc3(0, 102, 255)) { - auto scene = CCDirector::sharedDirector()->getRunningScene(); - if (scene->getChildrenCount() == 0) return; - auto layer = scene->getChildren()->objectAtIndex(0); - std::string layerName = misc::getNodeName(layer); - ret->setColor(Mod::get()->template getSettingValue("background")); + }), + arc::selectee(crx.recv(), [&](auto req) { + if (req) { + bool b = std::move(req).unwrap(); + log::debug("Cancelled (Code = {})", b); + } else { + log::debug("Cancelled (Code = Unknown)"); } - ret->release(); - } - }); - - } - return ret; - } -}; - -// Child background -class $modify(UtilCCScale9, cocos2d::extension::CCScale9Sprite) { - static cocos2d::extension::CCScale9Sprite* create(char const* name, CCRect rect) { - auto ret = cocos2d::extension::CCScale9Sprite::create(name, rect); - if (ret == nullptr) return ret; - // better code, thanks camila! - if ((!strcmp(name, "square02b_001.png") || !strcmp(name, "square02b_small.png")) && Mod::get()->template getSettingValue("activate-background")) { - ret->retain(); - Loader::get()->queueInMainThread([=] { - if (ret != nullptr) { - // jouca waht - if (ret->getColor() == ccc3(0, 56, 141)) { - ccColor3B new_color = Mod::get()->template getSettingValue("child-background"); - if (Mod::get()->template getSettingValue("syncBGcolor")) { - new_color = Mod::get()->template getSettingValue("background"); - } - if (Mod::get()->template getSettingValue("addChildBDGradient")) { - new_color = ccc3(new_color.r * 0.79, new_color.g * 0.79, new_color.b * 0.79); - } - if (Mod::get()->template getSettingValue("bgchild-transparency")) { - int opacity = Mod::get()->template getSettingValue("bgchild-transparency-scroll"); - ret->setOpacity(opacity); - } - ret->setColor(new_color); - } else if (ret->getColor() == ccc3(0, 39, 98)) { - ccColor3B new_color = Mod::get()->template getSettingValue("child-background"); - if (Mod::get()->template getSettingValue("syncBGcolor")) { - new_color = Mod::get()->template getSettingValue("background"); - } - if (Mod::get()->template getSettingValue("addChildBDGradient")) { - new_color = ccc3(new_color.r * 0.71, new_color.g * 0.71, new_color.b * 0.71); - } - if (Mod::get()->template getSettingValue("bgchild-transparency")) { - int opacity = Mod::get()->template getSettingValue("bgchild-transparency-scroll"); - ret->setOpacity(opacity); - } - ret->setColor(new_color); - } else if (ret->getColor() == ccc3(0, 46, 117)) { - ccColor3B new_color = Mod::get()->template getSettingValue("child-background"); - if (Mod::get()->template getSettingValue("syncBGcolor")) { - new_color = Mod::get()->template getSettingValue("background"); - } - if (Mod::get()->template getSettingValue("addChildBDGradient")) { - new_color = ccc3(new_color.r * 0.74, new_color.g * 0.74, new_color.b * 0.74); - } - if (Mod::get()->template getSettingValue("bgchild-transparency")) { - int opacity = Mod::get()->template getSettingValue("bgchild-transparency-scroll"); - ret->setOpacity(opacity); - } - ret->setColor(new_color); - } else if (ret->getColor() == ccc3(0, 36, 91)) { - ccColor3B new_color = Mod::get()->template getSettingValue("child-background"); - if (Mod::get()->template getSettingValue("syncBGcolor")) { - new_color = Mod::get()->template getSettingValue("background"); - } - if (Mod::get()->template getSettingValue("addChildBDGradient")) { - new_color = ccc3(new_color.r * 0.70, new_color.g * 0.70, new_color.b * 0.70); - } - if (Mod::get()->template getSettingValue("bgchild-transparency")) { - int opacity = Mod::get()->template getSettingValue("bgchild-transparency-scroll"); - ret->setOpacity(opacity); - } - ret->setColor(new_color); - } else if (ret->getColor() == ccc3(0, 31, 79)) { - ccColor3B new_color = Mod::get()->template getSettingValue("child-background"); - if (Mod::get()->template getSettingValue("syncBGcolor")) { - new_color = Mod::get()->template getSettingValue("background"); - } - if (Mod::get()->template getSettingValue("addChildBDGradient")) { - new_color = ccc3(new_color.r * 0.67, new_color.g * 0.67, new_color.b * 0.67); - } - if (Mod::get()->template getSettingValue("bgchild-transparency")) { - int opacity = Mod::get()->template getSettingValue("bgchild-transparency-scroll"); - ret->setOpacity(opacity); + Loader::get()->queueInMainThread([]() { + if (auto scene = CCScene::get()) { + EventsPush::eventCompletedCallback(scene); } - ret->setColor(new_color); - } - ret->release(); - } - }); - } - return ret; - } -}; -#endif - -//bool is_dailychest_ready = false; -bool is_socketserver_started = false; -class $modify(MenuLayer) { - bool init() { - if (!MenuLayer::init()) return false; - - /*if (!is_dailychest_ready) { - std::thread hThread(dailyChestThread); - hThread.detach(); - is_dailychest_ready = true; - }*/ - if (!is_socketserver_started) { - bool startSocketServer = Mod::get()->template getSettingValue("socketServer"); - if (startSocketServer) { - if (!Mod::get()->hasSavedValue("clientId")) { - Mod::get()->setSavedValue("clientId", misc::genClientID()); - } - if (!Mod::get()->hasSavedValue("clientId")) { - Notification::create("Couldn't connect to server, invalid Client ID", NotificationIcon::Error)->show(); - return true; - } - std::thread hThread([]() { - AMQT handler(Mod::get()->getSavedValue("clientId")); - handler.connect(); - }); - hThread.detach(); - } - is_socketserver_started = true; - } - return true; - } -}; - -void toggleSpriteHooks(bool value) { - for (auto& hook : geode::Mod::get()->getHooks()) { - if (hook->getDisplayName() == "cocos2d::CCSprite::create" || hook->getDisplayName() == "cocos2d::extension::CCScale9Sprite::create") { - if (value) { - (void)hook->enable(); - } else { - (void)hook->disable(); - } + }); + }) + ); } - } -} - -$execute { - (void)Mod::get()->registerCustomSettingType("credit-buttons", &SettingCreditsValue::parse); - //(void)Mod::get()->registerCustomSettingType("notificationPlacement", &SettingPosValue::parse); - auto ret = Mod::get()->registerCustomSettingType("notification-placement", &SettingPosValue::parse); - if (!ret) { - log::error("Unable to register setting type: {}", ret.unwrapErr()); - } - Loader::get()->queueInMainThread([]{ - CCScheduler::get()->scheduleSelector(schedule_selector(EventHandler::check), EventHandler::create(), 1.0F, false); - //CCScheduler::get()->scheduleUpdateForTarget(EventHandler::create(), Priority::Last, false); }); - listenForSettingChanges("activate-background", [](bool value) { - log::info("Activate Background changed to {}", value); - toggleSpriteHooks(value); + /*auto watcher = FileWatcher::getForDirectory("gdutils"); + watcher->watch("gdutils.heartbeat", [] { }); + async::runtime().spawn([]() -> arc::Future<> { + co_return; + });*/ } -// When the socket connection is made -$on_mod(Loaded) { - log::info("GDUtils Mod Loaded"); - - if (!Mod::get()->getSettingValue("activate-background")) { - toggleSpriteHooks(false); - } - chestQueue.push(1); - - //Discord::init(); for next update ;) - // also for whatever reason, discord rpc doesnt work on vanilla gd, instead it shows absolutes MH icon for some reason even though I dont own MH. can someone explain that - - #ifdef GEODE_IS_WINDOWS - #include - #include - - std::array buffer; - GetModuleFileNameW(NULL, buffer.data(), MAX_PATH); - auto aaaa = buffer.data(); - std::wstring_convert> converter; - std::string nameStr = fmt::format("cmd /k cd \"{}\\gdutils\" && \"gd_protocol.bat\" %1 && exit", dirs::getGameDir()); - - std::wstring fullPath = std::wstring(buffer.data()); - size_t lastBackslashPos = fullPath.find_last_of(L"\\"); - std::wstring exeName; - if (lastBackslashPos != std::wstring::npos) { - exeName = fullPath.substr(lastBackslashPos + 1); - } - - // Create the key for the custom protocol in user registry - HKEY hCurrentUserKey; - if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Classes", 0, KEY_SET_VALUE, &hCurrentUserKey) == ERROR_SUCCESS) { - HKEY hKey; - if (RegCreateKeyEx(hCurrentUserKey, "gdutils", 0, NULL, 0, KEY_SET_VALUE, NULL, &hKey, NULL) == ERROR_SUCCESS) { - // Define the default value for the protocol key - if (RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE*)"URL:gdutils Protocol", sizeof("URL:gdutils Protocol")) == ERROR_SUCCESS) { - // Create the key "shell\open\command" for specify the exe path - HKEY hCommandKey; - if (RegCreateKeyEx(hKey, "shell\\open\\command", 0, NULL, 0, KEY_SET_VALUE, NULL, &hCommandKey, NULL) == ERROR_SUCCESS) { - if (RegSetValueExA(hCommandKey, NULL, 0, REG_SZ, (const BYTE*)nameStr.c_str(), nameStr.length() + 1) == ERROR_SUCCESS) { - log::info("Le protocole a été enregistré avec succès pour cet utilisateur."); - } else { - log::error("Erreur lors de la définition de la valeur du chemin de l'exécutable."); - } - RegCloseKey(hCommandKey); - } else { - log::error("Erreur lors de la création de la clé shell\\open\\command."); - } - - RegSetValueEx(hKey, "URL Protocol", 0, REG_SZ, NULL, NULL); - } else { - log::error("Erreur lors de la définition de la valeur par défaut du protocole."); - } - RegCloseKey(hKey); - } else { - log::error("Erreur lors de la création de la clé du protocole."); +$on_game(Loaded) { + if (g_socket_server_ran) return; + if (geode::Mod::get()->getSettingValue("socketServer")) { + g_socket_server_ran = true; + if (!Mod::get()->hasSavedValue("clientId")) { + // this is just for statistics ok + #ifdef GEODE_IS_WINDOWS + std::string platform = "Windows"; + #elif defined(GEODE_IS_ANDROID) + std::string platform = "Android"; + #elif defined(GEODE_IS_MACOS) + std::string platform = "Mac"; + #elif defined(GEODE_IS_IOS) + std::string platform = "iOS"; + #else + std::string platform = "Unknown"; + #endif + const std::string charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dist(0, charset.size() - 1); + std::string randomStr; + for (size_t i = 0; i < 8; ++i) { + randomStr.push_back(charset[dist(gen)]); + } + auto now = std::chrono::system_clock::now(); + auto now_ms = std::chrono::duration_cast(now.time_since_epoch()).count(); + int accountID = 0; + if (auto gjam = GJAccountManager::get()) { + accountID = gjam->m_accountID; + } + Mod::get()->setSavedValue("clientId", fmt::format("gdutils-{}-{}-{}-{}", accountID, platform, now_ms, randomStr)); + } + if (!Mod::get()->hasSavedValue("clientId")) { + Notification::create("Couldn't connect to server, invalid Client ID", NotificationIcon::Error)->show(); + return; } - RegCloseKey(hCurrentUserKey); - } else { - log::error("Erreur lors de l'ouverture de la clé du registre utilisateur."); + std::thread hThread([]() mutable { + AMQT handler(Mod::get()->getSavedValue("clientId")); + handler.connect(); + }); + hThread.detach(); } - - std::filesystem::create_directory("gdutils"); - if (!std::filesystem::exists("gdutils/gd_protocol.bat")) { - std::ofstream file("gdutils/gd_protocol.bat"); - file << R"( -@echo off -setlocal enabledelayedexpansion - - )"; - file << fmt::format("set \"appName={}\"", converter.to_bytes(exeName)); - file << R"( -set "argument=%1" -set "number=" - -REM Check if the argument contains / -echo !argument! | find "/" > nul -if not errorlevel 1 ( - REM If / is found, extract the number part after the / - for /f "tokens=2 delims=/" %%a in ("!argument!") do ( - set "number=%%a" - ) -) else ( - REM If / is not found, the argument is in the format gdutils:123 - for /f "tokens=2 delims=:" %%a in ("!argument!") do ( - set "number=%%a" - ) -) - -if not defined number ( - echo Invalid argument format: %1 - exit /b 1 -) - -set "flagFile=%number%.flag" - -REM Check if the application is already running -tasklist /FI "IMAGENAME eq %appName%" | find /i "%appName%" > nul -if errorlevel 1 ( - REM If not running, start the application with the provided argument - cd .. - start "" "%appName%" - cd gdutils - type nul > "%flagFile%" -) else ( - REM If running, create an empty file based on the extracted number - type nul > "%flagFile%" -) - -endlocal - )"; - file.close(); - } - - #endif } diff --git a/src/modules/QueueHandler.cpp b/src/modules/QueueHandler.cpp new file mode 100644 index 0000000..8708d1e --- /dev/null +++ b/src/modules/QueueHandler.cpp @@ -0,0 +1,10 @@ +#include "QueueHandler.hpp" + +std::queue rateQueue; + +std::queue QueueHandler::getRateQueue() { + return rateQueue; +}; +void QueueHandler::addToRate(std::string value) { + rateQueue.push(value); +} diff --git a/src/modules/QueueHandler.hpp b/src/modules/QueueHandler.hpp new file mode 100644 index 0000000..d6486dc --- /dev/null +++ b/src/modules/QueueHandler.hpp @@ -0,0 +1,7 @@ +#pragma once +#include + +namespace QueueHandler { + std::queue getRateQueue(); + void addToRate(std::string); +} diff --git a/src/Utils/SpotifyHandler.cpp b/src/modules/SpotifyHandler.cpp similarity index 87% rename from src/Utils/SpotifyHandler.cpp rename to src/modules/SpotifyHandler.cpp index a2265fa..444cca8 100644 --- a/src/Utils/SpotifyHandler.cpp +++ b/src/modules/SpotifyHandler.cpp @@ -1,16 +1,15 @@ // Spotify +// sorry this code will forever be bad bool is_muted = false; -#include "../includes.h" +#include #include #include #include -#include "../Settings/CustomSettings.hpp" #ifdef GEODE_IS_WINDOWS #include #include #include #include -#include #include #include #include @@ -230,18 +229,13 @@ void toggleSpotifyMute(bool automatic = false, bool muted = false) { class $modify(PlayLayer) { bool init(GJGameLevel* level, bool p1, bool p2) { if (!PlayLayer::init(level, p1, p2)) return false; - if (!Mod::get()->getSettingValue("inLevelsSpotify")) return true; - //auto gm = FMODAudioEngine::sharedEngine(); - //if (gm->m_backgroundMusicVolume > 0.0f) { - // uncomment when fmod gets these fields - if (1.0F > 0.0F) { + if (FMODAudioEngine::sharedEngine()->m_musicVolume > 0.0F) { toggleSpotifyMute(true, true); } return true; } void onQuit() { PlayLayer::onQuit(); - if (!Mod::get()->getSettingValue("inLevelsSpotify")) return; if (is_muted) { toggleSpotifyMute(true, false); } @@ -254,8 +248,7 @@ class $modify(PauseLayer) { void goEdit() { PauseLayer::goEdit(); if (!Mod::get()->getSettingValue("inLevelsSpotify")) return; - //if (gm->m_backgroundMusicVolume > 0.0f) { - if (1 > 0.0F) { // temp until someone adds fields + if (FMODAudioEngine::sharedEngine()->m_musicVolume > 0.0F) { // temp until someone adds fields toggleSpotifyMute(); } } @@ -264,45 +257,66 @@ class $modify(PauseLayer) { class $modify(EditorUI) { void onPlaytest(CCObject* sender) { EditorUI::onPlaytest(sender); - if (!Mod::get()->getSettingValue("inEditorSpotify")) return; - //if (gm->m_backgroundMusicVolume > 0.0f) { - if (1 > 0.0F) { // temp until someone adds fields + if (FMODAudioEngine::sharedEngine()->m_musicVolume > 0.0F) { // temp until someone adds fields toggleSpotifyMute(); } } void onStopPlaytest(CCObject* sender) { EditorUI::onStopPlaytest(sender); - if (!Mod::get()->getSettingValue("inEditorSpotify")) return; - if (is_muted) { toggleSpotifyMute(true, false); } } void playtestStopped() { EditorUI::playtestStopped(); - if (!Mod::get()->getSettingValue("inEditorSpotify")) return; - if (is_muted) { toggleSpotifyMute(true, false); } } void onPlayback(CCObject* sender) { EditorUI::onPlayback(sender); - if (!Mod::get()->getSettingValue("inEditorSpotify")) return; - - //if (gm->m_backgroundMusicVolume > 0.0f) { - if (1 > 0.0F) { // temp until someone adds fields + if (FMODAudioEngine::sharedEngine()->m_musicVolume > 0.0F) { // temp until someone adds fields toggleSpotifyMute(); } } void onPause(CCObject* sender) { if (is_muted) { - if (Mod::get()->getSettingValue("inEditorSpotify")) { - toggleSpotifyMute(true, false); - } + toggleSpotifyMute(true, false); } EditorUI::onPause(sender); } }; #endif // Spotify + +void toggleHook(bool level, bool value) { + for (auto& hook : geode::Mod::get()->getHooks()) { + if (level && !hook->getDisplayName().starts_with("PauseLayer") && !hook->getDisplayName().starts_with("PlayLayer")) continue; + if (!level && !hook->getDisplayName().starts_with("EditorUI")) continue; + if (value) { + (void)hook->enable(); + } else { + (void)hook->disable(); + } + } +} + +$execute { + listenForSettingChanges("inLevelsSpotify", [](bool value) { + log::info("Spotify In Level changed to {}", value); + toggleHook(true, value); + }); + listenForSettingChanges("inEditorSpotify", [](bool value) { + log::info("Spotify In Editor changed to {}", value); + toggleHook(false, value); + }); +} + +$on_mod(Loaded) { + if (!Mod::get()->getSettingValue("inLevelsSpotify")) { + toggleHook(true, false); + } + if (!Mod::get()->getSettingValue("inEditorSpotify")) { + toggleHook(false, false); + } +} diff --git a/src/modules/events/DailyChest.cpp b/src/modules/events/DailyChest.cpp new file mode 100644 index 0000000..0a41bdc --- /dev/null +++ b/src/modules/events/DailyChest.cpp @@ -0,0 +1,301 @@ +#include "DailyChest.hpp" +#include +#include "../include/RateEvent.hpp" +using namespace asp::time; + +#if defined(GEODE_IS_WINDOWS) +#include +#include +#else +#include +#endif + +inline double rob_seconds(int remaining) { + if (remaining == 0) return 0; +#ifdef GEODE_IS_WINDOWS + __timeb64 current; + _ftime64_s(¤t); + // nice robert, i dunno if the bitmasking was intentional + auto result = (((double)((current.time & 0xFFFFF) * 1000 + current.millitm)) / 1000.0); +#else + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + auto result = ((double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0); +#endif + if (remaining < 0) return result; + return remaining - result; +} + +enum class ChestKind { + Small, + Large +}; + +struct ChestMsg { + enum class Type { + Refresh, + Opened, + Stop + } type; + + uint32_t smallTime = 0; + uint32_t largeTime = 0; + ChestKind opened{}; +}; + +static std::optional> g_chestTx; +static DailyChest* g_pendingRefresh = nullptr; + +static void clearDelegateIfSelf(DailyChest* self) { + auto glm = GameLevelManager::sharedState(); + if (glm && glm->m_GJRewardDelegate == self) { + glm->m_GJRewardDelegate = nullptr; + } +} + +DailyChest::~DailyChest() { + clearDelegateIfSelf(this); +} + +void DailyChest::getRewards() { + auto glm = GameLevelManager::sharedState(); + if (glm) { + glm->m_GJRewardDelegate = this; + glm->getGJRewards(0); + } +}; + +#include +void DailyChest::rewardsStatusFinished(int p0) { + auto gsm = GameStatsManager::sharedState(); + if (gsm->m_rewardItems->count() == 0) { + log::debug("[DailyChest] no reward items, aborting"); + clearDelegateIfSelf(this); + if (g_pendingRefresh == this) { g_pendingRefresh = nullptr; this->release(); } + return; + } + + auto item1 = typeinfo_cast(gsm->m_rewardItems->objectForKey(0x1)); + auto item2 = typeinfo_cast(gsm->m_rewardItems->objectForKey(0x2)); + uint32_t t1 = item1 ? (uint32_t)rob_seconds(item1->m_timeRemaining) : 0; + uint32_t t2 = item2 ? (uint32_t)rob_seconds(item2->m_timeRemaining) : 0; + + log::debug("[DailyChest] parsed timers: small={}s large={}s", t1, t2); + + if (g_chestTx) { + (void)g_chestTx->trySend(ChestMsg{ + .type = ChestMsg::Type::Refresh, + .smallTime = t1, + .largeTime = t2 + }); + } + clearDelegateIfSelf(this); + if (g_pendingRefresh == this) { g_pendingRefresh = nullptr; this->release(); } +}; + +void DailyChest::rewardsStatusFailed() { + log::error("[DailyChest] Failed to get rewards"); + clearDelegateIfSelf(this); + if (g_pendingRefresh == this) { g_pendingRefresh = nullptr; this->release(); } +}; + +static void refreshRewards() { + if (g_pendingRefresh) { + g_pendingRefresh->release(); + g_pendingRefresh = nullptr; + } + auto dailyChest = new DailyChest(); + g_pendingRefresh = dailyChest; + dailyChest->getRewards(); +} + +static void giveChestNotify(bool large) { + Loader::get()->queueInMainThread([large]() { + EventData data; + data.sprite = "GJ_square04.png"; + data.level_name = " "; + data.level_creator = " "; + if (large) { + data.type = EventType::largeChest; + data.title = "Big Daily Chest available!"; + } else { + data.type = EventType::smallChest; + data.title = "Small Daily Chest available!"; + } + GDUtils::Events::RateEvent::emit(data); + }); +} + +// TODO: test RewardUnlockLayer::playRewardEffect to fix mod menus from skipping step2 +#include +class $modify(RULHook, RewardUnlockLayer) { + void step2() { + int tag = m_chestType; + if (g_chestTx) { + if (tag == 1) { + (void)g_chestTx->trySend({ + .type = ChestMsg::Type::Opened, + .opened = ChestKind::Small + }); + } else if (tag == 2) { + (void)g_chestTx->trySend({ + .type = ChestMsg::Type::Opened, + .opened = ChestKind::Large + }); + } + } + RewardUnlockLayer::step2(); + // Delay the refresh so it doesn't race with the chest UI's own getGJRewards request. + // GD only allows one getGJRewards request at a time. + // A typical request takes 1-3s; 5s gives enough margin even on slow connections. + async::runtime().spawn([]() -> arc::Future<> { + co_await arc::sleepFor(Duration::fromSecs(5)); + Loader::get()->queueInMainThread(refreshRewards); + }); + } +}; + +static void toggleHook(bool value) { + for (auto& hook : geode::Mod::get()->getHooks()) { + if (hook->getDisplayName() == "RewardUnlockLayer::playRewardEffect") { + (void)(value ? hook->enable() : hook->disable()); + } + } +} + +static void startChestWatcher() { + if (g_chestTx) return; + auto [tx, rx] = arc::mpsc::channel(); + g_chestTx = std::move(tx); + async::runtime().spawn([rx = std::move(rx)]() mutable -> arc::Future<> { + uint32_t smallRemaining = 0; + uint32_t largeRemaining = 0; + bool smallAwait = false; + bool largeAwait = false; + bool smallNotified = false; + bool largeNotified = false; + arc::CancellationToken cancel; + bool running = true; + + while (running) { + uint32_t nextWake = UINT32_MAX; + if (smallAwait) nextWake = std::min(nextWake, smallRemaining); + if (largeAwait) nextWake = std::min(nextWake, largeRemaining); + + log::debug( + "[DailyChest] loop: small={} ({}s), large={} ({}s)", + smallAwait, smallRemaining, + largeAwait, largeRemaining + ); + + co_await arc::select( + arc::selectee( + cancel.waitCancelled(), + [&] { running = false; } + ), + arc::selectee( + (nextWake != UINT32_MAX) + ? arc::sleepFor(Duration::fromSecs(nextWake)) + : arc::sleepFor(Duration::fromSecs(30)), + [&] { + log::debug("[DailyChest] sleep -> called! (after {}s)", nextWake); + if (smallAwait && smallRemaining == nextWake) { + log::debug("[DailyChest] sleep -> small chest notify"); + smallAwait = false; + smallNotified = true; + giveChestNotify(false); + } + if (largeAwait && largeRemaining == nextWake) { + log::debug("[DailyChest] sleep -> large chest notify"); + largeAwait = false; + largeNotified = true; + giveChestNotify(true); + } + } + ), + arc::selectee(rx.recv(), [&](auto req) { + if (req) { + log::debug("[DailyChest] rx -> called!"); + ChestMsg msg = std::move(req).unwrap(); + switch (msg.type) { + case ChestMsg::Type::Opened: + log::debug("[DailyChest] rx -> chest opened: {}", msg.opened == ChestKind::Small ? "small" : "large"); + if (msg.opened == ChestKind::Small) { + smallAwait = false; + smallNotified = false; + } else { + largeAwait = false; + largeNotified = false; + } + break; + case ChestMsg::Type::Refresh: + log::debug( + "[DailyChest] rx -> refresh: small={}s large={}s", + msg.smallTime, msg.largeTime + ); + if (msg.smallTime == 0) { + if (!smallAwait && !smallNotified) { + log::debug("[DailyChest] rx -> small chest notify"); + giveChestNotify(false); + } + smallAwait = false; + smallNotified = true; + smallRemaining = 0; + } else { + smallRemaining = msg.smallTime; + smallAwait = true; + } + if (msg.largeTime == 0) { + if (!largeAwait && !largeNotified) { + log::debug("[DailyChest] rx -> large chest notify"); + giveChestNotify(true); + } + largeAwait = false; + largeNotified = true; + largeRemaining = 0; + } else { + largeRemaining = msg.largeTime; + largeAwait = true; + } + break; + case ChestMsg::Type::Stop: + log::debug("[DailyChest] rx -> stop"); + cancel.cancel(); + return; + } + } + }) + ); + } + }); + refreshRewards(); +} + +static void stopChestWatcher() { + if (!g_chestTx) return; + toggleHook(false); + (void)g_chestTx->trySend({ ChestMsg::Type::Stop }); + g_chestTx = std::nullopt; +} + +$on_game(Loaded) { + if (Mod::get()->getSettingValue("largeChest") || Mod::get()->getSettingValue("smallChest")) { + startChestWatcher(); + } else { + toggleHook(false); + } + listenForSettingChanges("smallChest", [](bool value) { + if (value) { + startChestWatcher(); + } else if (!Mod::get()->getSettingValue("largeChest")) { + stopChestWatcher(); + } + }); + listenForSettingChanges("largeChest", [](bool value) { + if (value) { + startChestWatcher(); + } else if (!Mod::get()->getSettingValue("smallChest")) { + stopChestWatcher(); + } + }); +} diff --git a/src/Notifications/DailyChest.h b/src/modules/events/DailyChest.hpp similarity index 56% rename from src/Notifications/DailyChest.h rename to src/modules/events/DailyChest.hpp index 964b9c7..a89bf50 100644 --- a/src/Notifications/DailyChest.h +++ b/src/modules/events/DailyChest.hpp @@ -3,9 +3,11 @@ #include using namespace geode::prelude; -class DailyChest : public CCNode, public GJRewardDelegate { +class DailyChest : public CCObject, public GJRewardDelegate { public: - void getRewards(unsigned int type); + ~DailyChest(); + void getRewards(); void rewardsStatusFinished(int p0) override; void rewardsStatusFailed() override; + static void startGame(); }; diff --git a/src/modules/events/EventsPush.cpp b/src/modules/events/EventsPush.cpp new file mode 100644 index 0000000..95ded17 --- /dev/null +++ b/src/modules/events/EventsPush.cpp @@ -0,0 +1,853 @@ +#include "EventsPush.hpp" +#include +#include +#include +#include + +std::queue g_eventQueue; +bool g_processingEvents = false; +std::optional> g_finishTx; +//extern std::optional> s_tx; + +const char* getDemonDifficultyIcon(int stars) { + switch(stars){ + case 3: + return "difficulty_07_btn_001.png"; + case 4: + return "difficulty_08_btn_001.png"; + case 5: + return "difficulty_09_btn_001.png"; + case 6: + return "difficulty_10_btn_001.png"; + default: + return "difficulty_06_btn_001.png"; + } +} +const char* getDifficultyIcon(int stars) { + switch(stars){ + case 10: + return "difficulty_01_btn_001.png"; + case 20: + return "difficulty_02_btn_001.png"; + case 30: + return "difficulty_03_btn_001.png"; + case 40: + return "difficulty_04_btn_001.png"; + case 50: + return "difficulty_05_btn_001.png"; + case 60: + return "difficulty_auto_btn_001.png"; + default: + return "difficulty_00_btn_001.png"; + } +} +// stole from GDR mod lol +GJDifficulty getDifficulty(int stars) { + switch(stars){ + case 0: + return GJDifficulty::NA; + case 10: + return GJDifficulty::Easy; + case 20: + return GJDifficulty::Normal; + case 30: + return GJDifficulty::Hard; + case 40: + return GJDifficulty::Harder; + case 50: + return GJDifficulty::Insane; + case 60: + return GJDifficulty::Auto; + default: + return GJDifficulty::NA; + } +} +GJDifficulty getDemonDifficulty(int stars) { + switch(stars){ + case 3: + return GJDifficulty::DemonEasy; + case 4: + return GJDifficulty::DemonMedium; + case 5: + return GJDifficulty::DemonInsane; + case 6: + return GJDifficulty::DemonExtreme; + default: + return GJDifficulty::Demon; + } +} + +bool EventsPush::init(EventData data) { + if (!CCLayer::init()) return false; + auto scene = CCDirector::sharedDirector()->getRunningScene(); + auto director = CCDirector::sharedDirector(); + auto winSize = director->getWinSize(); + // type + // 0 = new rate + // 1 = daily + // 2 = weekly + + // rate + // 0 = unrated / star rate + // 1 = featured + // 2 = epic + // {'demon': 0, 'type': 0, 'starsum': 20, 'stars': 2, 'rate': 2, 'title': 'New Rated Level !', 'level_name': 'Pourquoi', 'level_creator': 'by Jouca', 'sprite': 'GJ_square01.png'} + int starsum = data.starsum; + int stars = data.stars; + int rateType = data.rate; + int coins = data.coins; + std::unordered_map sKeys { + { EventType::Rate, "newRate" }, + { EventType::Daily, "daily" }, + { EventType::Weekly, "weekly" }, + { EventType::smallChest, "event" }, + { EventType::largeChest, "smallChest" }, + { EventType::List, "largeChest" }, + { EventType::Event, "newListRate" }, + { EventType::Announcement, "announcement" }, + }; + eventType = data.type; + auto it = sKeys.find(data.type); + if (it != sKeys.end()) { + if (!Mod::get()->getSettingValue(it->second)) { + EventsPush::eventCompletedCallback(scene); + return true; + } + } + float lrScale = (float)Mod::get()->template getSettingValue("size"); + auto bg = Build::create(data.sprite.c_str()).scale(lrScale).contentSize(240, 70).collect(); + // 0 / 0 = bottom left + // screen width / screen height = top right + // screen width divided by 2 / screen height divided by 2 = middle + this->addChild(bg); + auto node = CCNode::create(); + + if (eventType != EventType::smallChest && eventType != EventType::largeChest && eventType != EventType::Announcement) { + CCSprite* diffFace; + GJDifficultySprite* mythic = nullptr; + if (!data.demon) { + diffFace = cocos2d::CCSprite::createWithSpriteFrameName(getDifficultyIcon(starsum)); + mythic = GJDifficultySprite::create(static_cast(getDifficulty(starsum)), static_cast(0)); + } else { + diffFace = cocos2d::CCSprite::createWithSpriteFrameName(getDemonDifficultyIcon(starsum)); + mythic = GJDifficultySprite::create(static_cast(getDemonDifficulty(starsum)), static_cast(0)); + } + + diffFace->setPosition({26.f, 43.f}); + diffFace->setScale(.8F); + CCSprite* moon = cocos2d::CCSprite::createWithSpriteFrameName("moon_small01_001.png"); + mythic->updateFeatureState(static_cast(4)); + + std::string starcountstr = std::to_string(stars); + auto starcount = cocos2d::CCLabelBMFont::create(starcountstr.c_str(), "bigFont.fnt"); + starcount->setPosition({25, 18}); + starcount->setAnchorPoint({1, 0.5}); + starcount->setScale(0.35f); + bg->addChild(starcount); + CCSprite* star; + if (eventType == EventType::List) { + star = cocos2d::CCSprite::createWithSpriteFrameName("diamond_small01_001.png"); + } else { + star = cocos2d::CCSprite::createWithSpriteFrameName("star_small01_001.png"); + } + star->setPosition({31, 18}); + star->setScale(.775F); + moon->setPosition({31, 18}); + moon->setScale(.775F); + + if (data.platformer) bg->addChild(moon); + else bg->addChild(star); + + mythic->setPosition({26.f, 43.f}); + mythic->setScale(.8F); + + switch (rateType) { + default: // Rate + bg->addChild(diffFace); + break; + case 1: // Featured + Build::createSpriteName("GJ_featuredCoin_001.png").pos(26,43).scale(.8f).parent(bg); + bg->addChild(diffFace); + break; + case 2: // Epic + Build::createSpriteName("GJ_epicCoin_001.png").pos(26,43).scale(.8f).parent(bg); + bg->addChild(diffFace); + break; + case 3: // Legendary + Build::createSpriteName("GJ_epicCoin2_001.png").pos(26,43).scale(.8f).parent(bg); + bg->addChild(diffFace); + if (Mod::get()->template getSettingValue("customDifficultyFaces")) { + CCSprite* legendaryFace = nullptr; + if (!data.demon) { + if (starsum >= 10) { + std::string diffStr = std::to_string(static_cast(getDifficulty(starsum))); + auto name = "difficulty_0" + diffStr + "_legendaryIcon.png"; + legendaryFace = CCSprite::create((""_spr+name).c_str()); + } + } else { + if (starsum < 6) { + std::string diffStr = std::to_string(static_cast(getDemonDifficulty(starsum))); + auto name = "difficulty_0" + diffStr + "_legendaryIcon.png"; + legendaryFace = CCSprite::create((""_spr+name).c_str()); + } else { + std::string diffStr = std::to_string(static_cast(getDemonDifficulty(starsum))); + auto name = "difficulty_" + diffStr + "_legendaryIcon.png"; + legendaryFace = CCSprite::create((""_spr+name).c_str()); + } + } + + if (legendaryFace != nullptr) { + legendaryFace->setPosition({26.f, 48.f}); + legendaryFace->setScale(.8F); + bg->addChild(legendaryFace); + } + } + break; + case 4: // Mythic + bg->addChild(mythic); + if (Mod::get()->template getSettingValue("customDifficultyFaces")) { + CCSprite* mythicFace = nullptr; + if (!data.demon) { + if (starsum >= 10) { + std::string diffStr = std::to_string(static_cast(getDifficulty(starsum))); + auto name = "difficulty_0" + diffStr + "_mythicIcon.png"; + mythicFace = CCSprite::create((""_spr+name).c_str()); + } + } else { + if (starsum < 6) { + std::string diffStr = std::to_string(static_cast(getDemonDifficulty(starsum))); + auto name = "difficulty_0" + diffStr + "_mythicIcon.png"; + mythicFace = CCSprite::create((""_spr+name).c_str()); + } else { + std::string diffStr = std::to_string(static_cast(getDemonDifficulty(starsum))); + auto name = "difficulty_" + diffStr + "_mythicIcon.png"; + mythicFace = CCSprite::create((""_spr+name).c_str()); + } + } + + if (mythicFace != nullptr) { + mythicFace->setPosition({26.f, 48.f}); + mythicFace->setScale(.8F); + bg->addChild(mythicFace); + } + } + + break; + } + + auto verifiedCoinSpr1 = cocos2d::CCSprite::createWithSpriteFrameName("GJ_coinsIcon2_001.png"); + verifiedCoinSpr1->setScale(0.35f); + auto verifiedCoinSpr2 = cocos2d::CCSprite::createWithSpriteFrameName("GJ_coinsIcon2_001.png"); + verifiedCoinSpr2->setScale(0.35f); + auto verifiedCoinSpr3 = cocos2d::CCSprite::createWithSpriteFrameName("GJ_coinsIcon2_001.png"); + verifiedCoinSpr3->setScale(0.35f); + + if (data.verified_coins == 0) { + verifiedCoinSpr1->setColor({255, 175, 75}); + verifiedCoinSpr2->setColor({255, 175, 75}); + verifiedCoinSpr3->setColor({255, 175, 75}); + } + + if (coins == 1 || coins == 3) { + verifiedCoinSpr2->setPosition({ -52, -22 }); + node->addChild(verifiedCoinSpr2); + + if (coins == 3) { + verifiedCoinSpr1->setPosition({ -60, -22 }); + verifiedCoinSpr3->setPosition({ -44, -22 }); + + node->addChild(verifiedCoinSpr1); + node->addChild(verifiedCoinSpr3); + } + } else if (coins == 2) { + verifiedCoinSpr1->setPosition({ -55, -22 }); + verifiedCoinSpr2->setPosition({ -48, -22 }); + + node->addChild(verifiedCoinSpr1); + node->addChild(verifiedCoinSpr2); + } + + // Progress Bar for lists + if (eventType == EventType::List) { + auto barSpriteBack = CCSprite::create("GJ_progressBar_001.png"); + barSpriteBack->setScaleX(0.38f); + barSpriteBack->setScaleY(0.45f); + barSpriteBack->setPosition({ 38, 3 }); + barSpriteBack->setPositionY(3 - 19.f); + barSpriteBack->setPositionX(38); + barSpriteBack->setColor({0, 0, 0}); + barSpriteBack->setOpacity(100); + barSpriteBack->setZOrder(10); + barSpriteBack->setID("progress-bar-list"_spr); + node->addChild(barSpriteBack); + + auto barSpriteTop = CCSprite::create("GJ_progressBar_001.png"); + barSpriteTop->setScaleY(0.4f); + barSpriteTop->setPosition({ 2, 10 }); + barSpriteTop->setAnchorPoint({0, 0.5}); + barSpriteTop->setOpacity(255); + barSpriteTop->setZOrder(11); + + CCPoint rectangle[4] = { + CCPoint(0, 0), + CCPoint(0, 20), + CCPoint(barSpriteBack->getScaledContentSize().width * -2.5f, 20), + CCPoint(barSpriteBack->getScaledContentSize().width * -2.5f, 0) + }; + + auto clippingNode = CCClippingNode::create(); + auto barMask = CCDrawNode::create(); + barMask->drawPolygon(rectangle, 4, ccc4FFromccc3B({0, 0, 0}), 0, ccc4FFromccc3B({0, 0, 0})); + clippingNode->setStencil(barMask); + clippingNode->addChild(barSpriteTop); + clippingNode->setPositionX(330); + barSpriteBack->addChild(clippingNode); + barSpriteTop->setPositionX(-666); + + // Get datas for levels + int maxToCompleteList = data.maxToCompleteList; + std::vector levels = geode::utils::string::split(data.levels_list, ","); + + // Get client data for levels + GameLevelManager* gameLevelManager = GameLevelManager::sharedState(); + CCArray* levelsData = gameLevelManager->getCompletedLevels(false); + + int completedLevels = 0; + int nbLevels = 0; + + while (levels.size() > 0) { + std::string id = levels[0]; + nbLevels++; + + for (int i = 0; i < levelsData->count(); i++) { + auto level = static_cast(levelsData->objectAtIndex(i)); + if (std::to_string(level->m_levelID) == id) { + if (level->m_normalPercent == 100) completedLevels++; + } + } + + levels.erase(levels.begin()); + } + + // min -666 | max -337 + // Calculate position for Progress Bar (between these values based on percentage) + float percentage; + CCLabelBMFont* progressText; + + if (completedLevels >= maxToCompleteList) { + percentage = (float)completedLevels / (float)nbLevels; + progressText = CCLabelBMFont::create((std::to_string(completedLevels) + "/" + std::to_string(nbLevels)).c_str(), "bigFont.fnt"); + barSpriteTop->setColor({ 100, 255, 255 }); + starcount->setColor({ 100, 255, 255 }); + + auto listCompleted = CCSprite::createWithSpriteFrameName("GJ_completesIcon_001.png"); + listCompleted->setPosition({ 94, -15 }); + listCompleted->setScale(0.55f); + listCompleted->setZOrder(13); + node->addChild(listCompleted); + } else { + percentage = (float)completedLevels / (float)maxToCompleteList; + progressText = CCLabelBMFont::create((std::to_string(completedLevels) + "/" + std::to_string(maxToCompleteList)).c_str(), "bigFont.fnt"); + barSpriteTop->setColor({ 255, 84, 50 }); + + auto listUncompleted = CCSprite::createWithSpriteFrameName("diamond_small01_001.png"); + listUncompleted->setPosition({ 94, -15 }); + listUncompleted->setScale(0.55f); + listUncompleted->setZOrder(13); + node->addChild(listUncompleted); + } + + auto moveAction = CCEaseSineOut::create(CCMoveBy::create(0.f, { (percentage * 337), 0 })); + barSpriteTop->runAction(moveAction); + + // Add text for Progress Bar + progressText->setPosition({ 38, -15 }); + progressText->setScale(0.35f); + progressText->setZOrder(13); + node->addChild(progressText); + } + } + + std::string titleStr = data.title; + CCPoint titlePos; + geode::Anchor titleAnchor = Anchor::Top; + switch (data.type) { + case EventType::smallChest: + titlePos = CCPoint(0, -14); + Build::createSpriteName("chest_01_02_001.png").scale(0.45f).parentAtPos(bg, Anchor::Center, {0,-8}); + break; + case EventType::largeChest: + titlePos = CCPoint(0, -14); + Build::createSpriteName("chest_02_02_001.png").scale(0.4f).parentAtPos(bg, Anchor::Center, {0,-8}); + break; + case EventType::List: // TEST + titlePos = CCPoint(-11, -15); + Build::createSpriteName("GJ_listAddBtn_001.png").anchorPoint(1,0).parentAtPos(bg, Anchor::BottomLeft, {7,7}); + break; + case EventType::Announcement: // TEST + titleStr = "Announcement"; + titlePos = CCPoint(-56, -14); + Build::create(data.title.c_str(), "bigFont.fnt").limitLabelWidth(200, 0.46f, 0.1f).anchorPoint(0, 0.5).parentAtPos(bg, Anchor::Left, {12,5}); + break; + default: + titlePos = CCPoint(-6, -17); + break; + } + Build::create(titleStr.c_str(), "goldFont.fnt").scale(0.575F).parentAtPos(bg, titleAnchor, titlePos); + + if (eventType != EventType::Announcement) { + auto level_title = cocos2d::CCLabelBMFont::create(data.level_name.c_str(), "bigFont.fnt"); + if (eventType == EventType::List) { + level_title->setPosition({ -27, 11 }); + } else { + level_title->setPosition({ -27, 3 }); + } + level_title->setScale(.46F); + + level_title->setAnchorPoint({ 0, 0.5 }); + + auto level_by = cocos2d::CCLabelBMFont::create(data.level_creator.c_str(), "goldFont.fnt"); + if (eventType == EventType::List) { + level_by->setPosition({ -27, -2 }); + } else { + level_by->setPosition({ -27, -11 }); + } + level_by->setScale(.46F); + level_by->limitLabelWidth(120, 0.46f, 0.1f); + level_by->setAnchorPoint({ 0, 0.5 }); + node->addChild(level_by); + level_title->limitLabelWidth(120, 0.46f, 0.1f); + node->addChild(level_title); + } + + if (eventType == EventType::Daily || eventType == EventType::Weekly || eventType == EventType::Event) { + CCSprite* crown; + if (eventType == EventType::Daily) { + crown = cocos2d::CCSprite::createWithSpriteFrameName("gj_dailyCrown_001.png"); + } else if (eventType == EventType::Event) { + crown = cocos2d::CCSprite::createWithSpriteFrameName("gj_eventCrown_001.png"); + } else { + crown = cocos2d::CCSprite::createWithSpriteFrameName("gj_weeklyCrown_001.png"); + } + crown->setScale(.45F); + crown->setPosition({ 45, 45 }); + node->addChild(crown); + } + + node->setAnchorPoint({ 0.5, 0.5 }); + node->setPosition({ 77, 30 }); + + bg->addChild(node); + + // Move action + + float delayTime = (float)Mod::get()->template getSettingValue("time"); + + float moveX = .0F; + switch (Mod::get()->getSettingValue("notificationPlacement")) { + case PositionEnum::TopLeft: // top left + bg->setPosition((-(bg->getContentSize().width / 2)) * lrScale, ((winSize.height - (bg->getContentSize().height / 2)) - (20 * lrScale))); + moveX = (bg->getContentSize().width) * lrScale; + break; + case PositionEnum::TopRight: // top right + bg->setPosition(winSize.width + ((bg->getContentSize().width / 2) * lrScale), ((winSize.height - (bg->getContentSize().height / 2)) - (20 * lrScale))); + moveX = -(bg->getContentSize().width * lrScale); + break; + case PositionEnum::BottomLeft: // bottom left + bg->setPosition((-(bg->getContentSize().width / 2)) * lrScale, (bg->getContentSize().height / 2) * lrScale); + moveX = (bg->getContentSize().width) * lrScale; + break; + case PositionEnum::BottomRight: // bottom right + bg->setPosition({ winSize.width + ((bg->getContentSize().width / 2) * lrScale), (bg->getContentSize().height / 2) * lrScale}); + moveX = -((bg->getContentSize().width) * lrScale); + break; + } + + if (Mod::get()->getSettingValue("sfx")) { + float volume = (Mod::get()->getSettingValue("sfx-link")) ? GameManager::get()->m_sfxVolume : Mod::get()->getSettingValue("sfx-volume"); + if (data.type != EventType::smallChest && data.type != EventType::largeChest) { + FMODAudioEngine::get()->playEffect("crystal01.ogg", 1, 1, volume); + } else { + FMODAudioEngine::get()->playEffect("reward01.ogg", 1, 1, volume); + } + } + + bg->runAction(CCSequence::create( + CCEaseOut::create(CCMoveBy::create(0.5f, { moveX, 0.0f }), 0.6f), + CCDelayTime::create(delayTime), + CCEaseIn::create(CCMoveBy::create(0.5f, { -moveX, 0.0f }), 0.6f), + CCDelayTime::create(0.5F), + CCCallFunc::create(this, callfunc_selector(EventsPush::destroySelf)), + nullptr + )); + + this->setZOrder(scene->getHighestChildZ() + 10); + this->setID("EventsPush"_spr); + return true; +} + +bool EventsPush::initold(EventData data) { + if (!CCLayer::init()) return false; + auto scene = CCDirector::sharedDirector()->getRunningScene(); + auto director = CCDirector::sharedDirector(); + auto winSize = director->getWinSize(); + // type + // 0 = new rate + // 1 = daily + // 2 = weekly + + // rate + // 0 = unrated / star rate + // 1 = featured + // 2 = epic + // {'demon': 0, 'type': 0, 'starsum': 20, 'stars': 2, 'rate': 2, 'title': 'New Rated Level !', 'level_name': 'Pourquoi', 'level_creator': 'by Jouca', 'sprite': 'GJ_square01.png'} + int starsum = data.starsum; + int stars = data.stars; + int coins = data.coins; + int areCoinsVerified = data.verified_coins; + std::unordered_map sKeys { + { EventType::Rate, "newRate" }, + { EventType::Daily, "daily" }, + { EventType::Weekly, "weekly" }, + { EventType::smallChest, "event" }, + { EventType::largeChest, "smallChest" }, + { EventType::List, "largeChest" }, + { EventType::Event, "newListRate" }, + { EventType::Announcement, "announcement" }, + }; + eventType = data.type; + auto it = sKeys.find(data.type); + if (it != sKeys.end()) { + if (!Mod::get()->getSettingValue(it->second)) { + EventsPush::eventCompletedCallback(scene); + return true; + } + } + float lrScale = (float)Mod::get()->getSettingValue("size"); + + auto node = Build::create().anchorPoint(0.5, 0.5).pos(77, 30).collect(); + auto bg = Build::create(data.sprite.c_str()).contentSize(240, 70).scale(lrScale).child(node).parent(this).collect(); + float moveX = 0.f; + switch (Mod::get()->getSettingValue("notificationPlacement")) { + case PositionEnum::TopLeft: // top left + bg->setPosition((-(bg->getContentSize().width / 2)) * lrScale, ((winSize.height - (bg->getContentSize().height / 2)) - (20 * lrScale))); + moveX = (bg->getContentSize().width) * lrScale; + break; + case PositionEnum::TopRight: // top right + bg->setPosition(winSize.width + ((bg->getContentSize().width / 2) * lrScale), ((winSize.height - (bg->getContentSize().height / 2)) - (20 * lrScale))); + moveX = -(bg->getContentSize().width * lrScale); + break; + case PositionEnum::BottomLeft: // bottom left + bg->setPosition((-(bg->getContentSize().width / 2)) * lrScale, (bg->getContentSize().height / 2) * lrScale); + moveX = (bg->getContentSize().width) * lrScale; + break; + case PositionEnum::BottomRight: // bottom right + bg->setPosition({ winSize.width + ((bg->getContentSize().width / 2) * lrScale), (bg->getContentSize().height / 2) * lrScale}); + moveX = -((bg->getContentSize().width) * lrScale); + break; + } + std::string titleStr = data.title; + CCPoint titlePos; + switch (data.type) { + case EventType::smallChest: + titlePos = CCPoint(-65, 26); + Build::createSpriteName("chest_01_02_001.png").scale(0.45f).pos(45, -3).parent(node); + break; + case EventType::largeChest: + titlePos = CCPoint(-54, 26); + Build::createSpriteName("chest_02_02_001.png").scale(0.4f).pos(45, -3).parent(node); + break; + case EventType::List: + titlePos = CCPoint(-27, 27); + Build::createSpriteName("GJ_listAddBtn_001.png").pos(139, -8).parent(node); + break; + case EventType::Announcement: + titleStr = "Announcement"; + titlePos = CCPoint(-65, 26); + Build::create(data.title.c_str(), "bigFont.fnt").limitLabelWidth(200, 0.46f, 0.1f).anchorPoint(0, 0.5).pos(-65, 10).parent(node); + break; + default: + titlePos = CCPoint(-27, 23); + break; + } + if (data.type != EventType::smallChest && data.type != EventType::largeChest && data.type != EventType::Announcement) { + if (data.platformer) { + Build::createSpriteName("moon_small01_001.png").scale(.775f).pos(31, 18).parent(bg); + } else { + Build::createSpriteName((data.type == EventType::List) ? "diamond_small01_001.png" : "star_small01_001.png").scale(.775f).pos(31, 18).parent(bg); + } + if (data.type != EventType::List) { + Build::createSpriteName((!data.demon) ? getDifficultyIcon(starsum) : getDemonDifficultyIcon(starsum)) + .pos(26, 43) + .scale(.8f) + .parent(bg); + GJDifficultySprite* mythic = GJDifficultySprite::create( + static_cast((!data.demon) ? getDifficulty(starsum) : getDemonDifficulty(starsum)), + static_cast(0) + ); + mythic->updateFeatureState(GJFeatureState::Mythic); + switch (data.rate) { + default: + break; + } + + CCSprite* featured = cocos2d::CCSprite::createWithSpriteFrameName("GJ_featuredCoin_001.png"); + CCSprite* epic = cocos2d::CCSprite::createWithSpriteFrameName("GJ_epicCoin_001.png"); + CCSprite* legendary = cocos2d::CCSprite::createWithSpriteFrameName("GJ_epicCoin2_001.png"); + mythic->updateFeatureState(static_cast(4)); + + Build::create(std::to_string(stars).c_str(), "bigFont.fnt").pos(25, 18).anchorPoint(1, 0.5).scale(0.35f).parent(bg); + + featured->setPosition({26.f, 43.f}); + epic->setPosition({26.f, 43.f}); + legendary->setPosition({26.f, 43.f}); + mythic->setPosition({26.f, 43.f}); + featured->setScale(.8F); + epic->setScale(.8F); + legendary->setScale(.8F); + mythic->setScale(.8F); + + switch (data.type) { + default: + break; + case 1: // Featured + bg->addChild(featured); + break; + case 2: // Epic + bg->addChild(epic); + break; + case 3: // Legendary + bg->addChild(legendary); + + if (Mod::get()->template getSettingValue("customDifficultyFaces")) { + CCSprite* legendaryFace = nullptr; + if (!data.demon) { + if (starsum >= 10) { + std::string diffStr = std::to_string(static_cast(getDifficulty(starsum))); + auto name = "difficulty_0" + diffStr + "_legendaryIcon.png"; + legendaryFace = CCSprite::create((""_spr+name).c_str()); + } + } else { + if (starsum < 6) { + std::string diffStr = std::to_string(static_cast(getDemonDifficulty(starsum))); + auto name = "difficulty_0" + diffStr + "_legendaryIcon.png"; + legendaryFace = CCSprite::create((""_spr+name).c_str()); + } else { + std::string diffStr = std::to_string(static_cast(getDemonDifficulty(starsum))); + auto name = "difficulty_" + diffStr + "_legendaryIcon.png"; + legendaryFace = CCSprite::create((""_spr+name).c_str()); + } + } + + if (legendaryFace != nullptr) { + legendaryFace->setPosition({26.f, 48.f}); + legendaryFace->setScale(.8F); + bg->addChild(legendaryFace); + } + } + + break; + case 4: // Mythic + bg->addChild(mythic); + + if (Mod::get()->template getSettingValue("customDifficultyFaces")) { + CCSprite* mythicFace = nullptr; + if (!data.demon) { + if (starsum >= 10) { + std::string diffStr = std::to_string(static_cast(getDifficulty(starsum))); + auto name = "difficulty_0" + diffStr + "_mythicIcon.png"; + mythicFace = CCSprite::create((""_spr+name).c_str()); + } + } else { + if (starsum < 6) { + std::string diffStr = std::to_string(static_cast(getDemonDifficulty(starsum))); + auto name = "difficulty_0" + diffStr + "_mythicIcon.png"; + mythicFace = CCSprite::create((""_spr+name).c_str()); + } else { + std::string diffStr = std::to_string(static_cast(getDemonDifficulty(starsum))); + auto name = "difficulty_" + diffStr + "_mythicIcon.png"; + mythicFace = CCSprite::create((""_spr+name).c_str()); + } + } + + if (mythicFace != nullptr) { + mythicFace->setPosition({26.f, 48.f}); + mythicFace->setScale(.8F); + bg->addChild(mythicFace); + } + } + + break; + } + + auto verifiedCoinSpr1 = cocos2d::CCSprite::createWithSpriteFrameName("GJ_coinsIcon2_001.png"); + verifiedCoinSpr1->setScale(0.35f); + auto verifiedCoinSpr2 = cocos2d::CCSprite::createWithSpriteFrameName("GJ_coinsIcon2_001.png"); + verifiedCoinSpr2->setScale(0.35f); + auto verifiedCoinSpr3 = cocos2d::CCSprite::createWithSpriteFrameName("GJ_coinsIcon2_001.png"); + verifiedCoinSpr3->setScale(0.35f); + + if (areCoinsVerified == 0) { + verifiedCoinSpr1->setColor({255, 175, 75}); + verifiedCoinSpr2->setColor({255, 175, 75}); + verifiedCoinSpr3->setColor({255, 175, 75}); + } + + if (coins == 1 || coins == 3) { + verifiedCoinSpr2->setPosition({ -52, -22 }); + node->addChild(verifiedCoinSpr2); + + if (coins == 3) { + verifiedCoinSpr1->setPosition({ -60, -22 }); + verifiedCoinSpr3->setPosition({ -44, -22 }); + + node->addChild(verifiedCoinSpr1); + node->addChild(verifiedCoinSpr3); + } + } else if (coins == 2) { + verifiedCoinSpr1->setPosition({ -55, -22 }); + verifiedCoinSpr2->setPosition({ -48, -22 }); + + node->addChild(verifiedCoinSpr1); + node->addChild(verifiedCoinSpr2); + } + } else { + + } + } else if (data.type == EventType::List) { + } + Build::create(titleStr.c_str(), "goldFont.fnt").scale(0.575F).pos(titlePos).anchorPoint(0, 0.5).parent(node); + + if (Mod::get()->getSettingValue("sfx")) { + float volume = (Mod::get()->getSettingValue("sfx-link")) ? GameManager::get()->m_sfxVolume : Mod::get()->getSettingValue("sfx-volume"); + if (data.type != EventType::smallChest && data.type != EventType::largeChest) { + FMODAudioEngine::get()->playEffect("crystal01.ogg", 1, 1, volume); + } else { + FMODAudioEngine::get()->playEffect("reward01.ogg", 1, 1, volume); + } + } + + bg->runAction(CCSequence::create( + CCEaseOut::create(CCMoveBy::create(0.5f, { moveX, 0.0f }), 0.6f), + CCDelayTime::create(Mod::get()->getSettingValue("time")), + //CCEaseIn::create(CCMoveBy::create(0.5f, { -moveX, 0.0f }), 0.6f), + //CCDelayTime::create(0.5F), + //CCCallFunc::create(this, callfunc_selector(EventsPush::destroySelf)), + nullptr + )); + + this->setZOrder(scene->getHighestChildZ() + 10); + this->setID("EventsPush"_spr); + return true; +} + +void EventsPush::processNextEvent(CCScene *self) { + if (!g_eventQueue.empty()) { + auto data = std::move(g_eventQueue.front()); + g_eventQueue.pop(); + g_processingEvents = true; + auto layer = EventsPush::create(data); + GDUtils::Events::OnRate(data.type).send(data); + if (layer && self) { + self->addChild(layer); + } + } +} + +void EventsPush::pushRateLevel(CCScene *self, EventData data) { + log::debug( + "EventData [\ndemon = {};\nstarsum = {};\nstars = {};\nrate = {};\ntype = {};\ntitle = {};\nsprite = {};\nlevel_name = {};\nlevel_creator = {};\ncoins = {};\nverified_coins = {};\nplatformer = {};\nlevel_id = {};\nlevels_list = {};\nmaxToCompleteList = {};\n]", + data.demon, + data.starsum, + data.stars, + data.rate, + data.typeToInt(), + data.title, + data.sprite, + data.level_name, + data.level_creator, + data.coins, + data.verified_coins, + data.platformer, + data.level_id, + data.levels_list, + data.maxToCompleteList + ); + g_eventQueue.push(data); + // Start processing events if no events are being processed currently. + if (!g_processingEvents) { + processNextEvent(self); + } +} +/* +payload = { + "type": 7, + "title": "test" +} +*/ + +void EventsPush::callCancel() { + if (g_finishTx) { + (void)g_finishTx->trySend(std::move(true)); + } +} +void EventsPush::eventCompletedCallback(CCScene *self) { + g_processingEvents = false; + processNextEvent(self); +} + +std::string getNodeName(cocos2d::CCObject* node) { +#ifdef GEODE_IS_WINDOWS + return typeid(*node).name() + 6; +#else + { + std::string ret; + + int status = 0; + auto demangle = abi::__cxa_demangle(typeid(*node).name(), 0, 0, &status); + if (status == 0) { + ret = demangle; + } + free(demangle); + + return ret; + } +#endif +} + +static std::string s_currentLayer; + +void EventsPush::setTx(arc::mpsc::Sender tx) { + g_finishTx = std::move(tx); +} + +bool EventsPush::canSendEvent(CCScene* scene) { + auto layer = scene->getChildren()->objectAtIndex(0); + std::string layerName = getNodeName(layer); + if (layerName == "cocos2d::CCLayerColor") return false; + if (layerName == "LoadingLayer") return false; + bool everywhereElse = Mod::get()->getSettingValue("everywhereElse"); + bool inLevels = Mod::get()->getSettingValue("inLevels"); + bool inEditor = Mod::get()->getSettingValue("inEditor"); + bool inPlatformers = Mod::get()->getSettingValue("inPlatformers"); + bool pushEvent = true; + if (layerName == "PlayLayer") { + if (!inLevels) pushEvent = false; + } + if (layerName == "LevelEditorLayer" && !inEditor) { + pushEvent = false; + } + if ((layerName != "LevelEditorLayer" && layerName != "PlayLayer") && !everywhereElse) { + pushEvent = false; + } + return pushEvent; +} +$execute { + GDUtils::Events::RateEvent().listen([](EventData const& e) { + auto json = matjson::Serialize::toJson(e); + std::string toStr = json.dump(0); + AMQT::sendToTx(std::move(toStr)); + return ListenerResult::Stop; + }).leak(); + // ".leak() is for global listeners pretty much" +} diff --git a/src/modules/events/EventsPush.hpp b/src/modules/events/EventsPush.hpp new file mode 100644 index 0000000..672c921 --- /dev/null +++ b/src/modules/events/EventsPush.hpp @@ -0,0 +1,58 @@ +#pragma once +#include +#include +#include "../../include/RateEvent.hpp" + +class EventsPush : public CCLayer { + protected: + bool m_alreadyDead = false; + EventType eventType = EventType::NA; + bool init(EventData data); + bool initold(EventData data); + void destroySelf() { + m_alreadyDead = true; + auto scene = CCDirector::get()->getRunningScene(); + if (scene->getChildByID("EventsPush"_spr) != nullptr) { + scene->removeChildByID("EventsPush"_spr); + } + eventCompletedCallback(scene); + } + public: + void onExit() override { + CCLayer::onExit(); + if (!m_alreadyDead) { + callCancel(); + } + } + void onClickBtn(CCObject*); + static void pushRateLevel(CCScene* self, std::string data) { + auto jsonStr = matjson::parse(data); + if (jsonStr.isErr()) { + log::error("Couldn't parse JSON string: {}", jsonStr.unwrapErr()); + } + auto eventData = matjson::Serialize::fromJson(jsonStr.unwrapOrDefault()); + if (eventData.isErr()) { + log::error("Couldn't parse JSON to EventData: {}", eventData.unwrapErr()); + } + pushRateLevel( + self, + eventData.unwrapOrDefault() + ); + } + static void pushRateLevel(CCScene* self, EventData data); + static void processNextEvent(CCScene* self); + static void eventCompletedCallback(CCScene* self); + static void callCancel(); + static std::vector getWords(std::string s, std::string delim); + static bool canSendEvent(CCScene* self); + static EventsPush* create(EventData data) { + auto ret = new EventsPush(); + if (ret && ret->init(data)) { + ret->autorelease(); + return ret; + } + CC_SAFE_DELETE(ret); + return nullptr; + } + static void setTx(arc::mpsc::Sender tx); +}; diff --git a/src/modules/secrets/BadApple.cpp b/src/modules/secrets/BadApple.cpp new file mode 100644 index 0000000..7def2c9 --- /dev/null +++ b/src/modules/secrets/BadApple.cpp @@ -0,0 +1,38 @@ +// SPOILERSSS +#include "BadApple.hpp" +#ifdef GEODE_IS_WINDOWS +#include "VideoPlayer.hpp" +#else // mac +#include +#include +#endif +BadApple* BadApple::create() { + auto pRet = new BadApple(); + if (pRet && pRet->BadApple::init()) { + pRet->autorelease(); + return pRet; + } + CC_SAFE_DELETE(pRet); + return nullptr; +}; + +bool BadApple::init() { + //#ifndef GEODE_IS_MACOS + #ifdef GEODE_IS_WINDOWS + videoplayer::VideoPlayer* player = videoplayer::VideoPlayer::create(Mod::get()->getSaveDir() / "bad_apple.mpg", true); + CCDirector* director = CCDirector::sharedDirector(); + CCSize size = director->getWinSize(); + player->setPosition(size.width / 2, size.height / 2); + player->setContentSize({ size.width - 40, size.height - 40 }); + player->setZOrder(-1); + this->addChild(player); + #endif + setKeypadEnabled(true); + + return true; +} + +void BadApple::keyBackClicked() { + setKeypadEnabled(false); + CCDirector::sharedDirector()->popSceneWithTransition(0.5f, PopTransition::kPopTransitionFade); +} diff --git a/src/Secret/BadApple.h b/src/modules/secrets/BadApple.hpp similarity index 65% rename from src/Secret/BadApple.h rename to src/modules/secrets/BadApple.hpp index 0451d05..8d0a46d 100644 --- a/src/Secret/BadApple.h +++ b/src/modules/secrets/BadApple.hpp @@ -1,9 +1,8 @@ // SPOILERSSS #pragma once -#include "../includes.h" -#include "VideoPlayer.hpp" +#include -class BadApple : public CCLayer { +class BadApple : public cocos2d::CCLayer { protected: virtual bool init(); virtual void keyBackClicked(); diff --git a/src/Secret/COTE.cpp b/src/modules/secrets/COTE.cpp similarity index 79% rename from src/Secret/COTE.cpp rename to src/modules/secrets/COTE.cpp index b7678c2..9a6e4a6 100644 --- a/src/Secret/COTE.cpp +++ b/src/modules/secrets/COTE.cpp @@ -1,7 +1,7 @@ // SPOILERSSS -#include "COTE.h" +#include "COTE.hpp" #ifdef GEODE_IS_WINDOWS -#include "../Utils/DownloadManager.h" +#include "VideoPlayer.hpp" #else // mac #include #include @@ -21,7 +21,7 @@ bool COTE::init() { auto menu = CCMenu::create(); //#ifndef GEODE_IS_MACOS #ifdef GEODE_IS_WINDOWS - videoplayer::VideoPlayer* player = videoplayer::VideoPlayer::create("./gdutils/cote.mpg", true); + videoplayer::VideoPlayer* player = videoplayer::VideoPlayer::create(Mod::get()->getSaveDir() / "cote.mpg", true); CCDirector* director = CCDirector::sharedDirector(); CCSize size = director->getWinSize(); player->setPosition(size.width / 2, size.height / 2); @@ -30,17 +30,12 @@ bool COTE::init() { this->addChild(player); #endif setKeypadEnabled(true); - return true; } void COTE::keyBackClicked() { setKeypadEnabled(false); - - #ifdef GEODE_IS_UNKNOWN - GameSoundManager::sharedManager()->playBackgroundMusic("./Resources/secretLoop02.mp3", true, false); - #endif CCDirector::sharedDirector()->popSceneWithTransition(0.5f, PopTransition::kPopTransitionFade); } -// cote time \ No newline at end of file +// cote time diff --git a/src/Secret/COTE.h b/src/modules/secrets/COTE.hpp similarity index 64% rename from src/Secret/COTE.h rename to src/modules/secrets/COTE.hpp index 7f3bfdd..75f4e39 100644 --- a/src/Secret/COTE.h +++ b/src/modules/secrets/COTE.hpp @@ -1,13 +1,12 @@ // SPOILERSSS #pragma once -#include "../includes.h" -#include "VideoPlayer.hpp" +#include -class COTE : public CCLayer { +class COTE : public cocos2d::CCLayer { protected: virtual bool init(); virtual void keyBackClicked(); public: static COTE* create(); -}; \ No newline at end of file +}; diff --git a/src/Secret/VideoPlayer.cpp b/src/modules/secrets/VideoPlayer.cpp similarity index 100% rename from src/Secret/VideoPlayer.cpp rename to src/modules/secrets/VideoPlayer.cpp diff --git a/src/Secret/VideoPlayer.hpp b/src/modules/secrets/VideoPlayer.hpp similarity index 100% rename from src/Secret/VideoPlayer.hpp rename to src/modules/secrets/VideoPlayer.hpp diff --git a/src/modules/settings/Credits.cpp b/src/modules/settings/Credits.cpp new file mode 100644 index 0000000..d05fadd --- /dev/null +++ b/src/modules/settings/Credits.cpp @@ -0,0 +1,27 @@ +#include "Credits.hpp" +#include +#include + +SettingNodeV3* CreditsValue::createNode(float width) { + return CreditsNode::create(static_pointer_cast(shared_from_this()), width); +} + +bool CreditsNode::init(std::shared_ptr setting, float width) { + if (!SettingNodeV3::init(setting, width)) + return false; + this->setContentSize({ width, 40.f }); + getNameLabel()->setVisible(false); + getButtonMenu()->setContentWidth(width); + Build::create("Credits", "bigFont.fnt", "GJ_button_01.png").scale(0.6f).intoMenuItem([]() { + CreditsMenu::create()->show(); + }).parentAtPos(getButtonMenu(), Anchor::Center, {-55, 0}); + Build::create("Beta Testers", "bigFont.fnt", "GJ_button_01.png").scale(0.6f).intoMenuItem([]() { + CreditsBetaMenu::create()->show(); + }).parentAtPos(getButtonMenu(), Anchor::Center, {85, 0}); + getButtonMenu()->updateLayout(); + return true; +} + +$execute { + (void)Mod::get()->registerCustomSettingType("credit-buttons", &CreditsValue::parse); +} diff --git a/src/modules/settings/Credits.hpp b/src/modules/settings/Credits.hpp new file mode 100644 index 0000000..b8744a9 --- /dev/null +++ b/src/modules/settings/Credits.hpp @@ -0,0 +1,49 @@ +#pragma once +#include + +class CreditsValue : public SettingV3 { +public: + static Result> parse(std::string const& key, std::string const& modID, matjson::Value const& json) { + auto res = std::make_shared(); + auto root = checkJson(json, "SettingCreditsValue"); + res->init(key, modID, root); + res->parseNameAndDescription(root); + res->parseEnableIf(root); + root.checkUnknownKeys(); + return root.ok(std::static_pointer_cast(res)); + } + + bool load(matjson::Value const& json) override { + return true; + } + bool save(matjson::Value& json) const override { + return true; + } + bool isDefaultValue() const override { + return true; + } + void reset() override {} + SettingNodeV3* createNode(float width) override; +}; +class CreditsNode : public SettingNodeV3 { +protected: + bool init(std::shared_ptr setting, float width); + void onCommit() override {} + void onResetToDefault() override {} +public: + bool hasUncommittedChanges() const override { + return false; + } + bool hasNonDefaultValue() const override { + return false; + } + static CreditsNode* create(std::shared_ptr setting, float width) { + auto ret = new CreditsNode(); + if (ret && ret->init(setting, width)) { + ret->autorelease(); + return ret; + } + CC_SAFE_DELETE(ret); + return nullptr; + } +}; diff --git a/src/modules/settings/Position.cpp b/src/modules/settings/Position.cpp new file mode 100644 index 0000000..814f3b5 --- /dev/null +++ b/src/modules/settings/Position.cpp @@ -0,0 +1,40 @@ +#include "Position.hpp" + +SettingNodeV3* PositionValue::createNode(float width) { + return PositionNode::create(static_pointer_cast(shared_from_this()), width); +} + +bool PositionNode::init(std::shared_ptr setting, float width) { + if (!SettingValueNodeV3::init(setting, width)) + return false; + this->setContentSize({ width, 70.f }); + getButtonMenu()->setContentSize({width / 2, 45.F}); + CCSprite* toggleOn = Build::createSpriteName("GJ_checkOn_001.png").scale(0.7f).collect(); + CCSprite* toggleOff = Build::createSpriteName("GJ_checkOff_001.png").scale(0.7f).collect(); + auto currentCorner = static_cast(this->getValue()); + Build::createToggle(toggleOn, toggleOff, [this](auto) { + onCornerClick(PositionEnum::TopLeft); + }).toggle(currentCorner != PositionEnum::TopLeft).parentAtPos(getButtonMenu(), Anchor::TopLeft).store(m_tlBtn); + Build::createToggle(toggleOn, toggleOff, [this](auto) { + onCornerClick(PositionEnum::TopRight); + }).toggle(currentCorner != PositionEnum::TopRight).parentAtPos(getButtonMenu(), Anchor::TopRight).store(m_trBtn); + Build::createToggle(toggleOn, toggleOff, [this](auto) { + onCornerClick(PositionEnum::BottomLeft); + }).toggle(currentCorner != PositionEnum::BottomLeft).parentAtPos(getButtonMenu(), Anchor::BottomLeft).store(m_blBtn); + Build::createToggle(toggleOn, toggleOff, [this](auto) { + onCornerClick(PositionEnum::BottomRight); + }).toggle(currentCorner != PositionEnum::BottomRight).parentAtPos(getButtonMenu(), Anchor::BottomRight).store(m_brBtn); + getButtonMenu()->updateLayout(); + getButtonMenu()->setAnchorPoint({0.5, 0.5}); + getButtonMenu()->updateAnchoredPosition(Anchor::Center, {0, 0}); + this->getNameLabel()->setVisible(false); + this->updateState(nullptr); + return true; +} + +$execute { + auto ret = Mod::get()->registerCustomSettingType("notification-placement", &PositionValue::parse); + if (!ret) { + log::error("Unable to register setting type: {}", ret.unwrapErr()); + } +} diff --git a/src/modules/settings/Position.hpp b/src/modules/settings/Position.hpp new file mode 100644 index 0000000..e2a7f91 --- /dev/null +++ b/src/modules/settings/Position.hpp @@ -0,0 +1,90 @@ +#pragma once +#include +enum class PositionEnum : int { + TopLeft, + TopRight, + BottomLeft, + BottomRight +}; +template <> +struct matjson::Serialize { + static matjson::Value toJson(PositionEnum const& value) { + switch (value) { + case PositionEnum::TopLeft: + return 1; + case PositionEnum::TopRight: + return 2; + case PositionEnum::BottomLeft: + return 3; + default: + case PositionEnum::BottomRight: + return 4; + } + } + static Result fromJson(matjson::Value const& value) { + switch (value.asInt().unwrapOrDefault()) { + case 1: return Ok(PositionEnum::TopLeft); + case 2: return Ok(PositionEnum::TopRight); + case 3: return Ok(PositionEnum::BottomLeft); + case 4: return Ok(PositionEnum::BottomRight); + default: return Err("Invalid PositionEnum value '{}'", value.asInt().unwrapOrDefault()); + } + } + static bool is_json(matjson::Value const& json) { + return json.isNumber() || json.isString(); + } +}; + +class PositionValue : public SettingBaseValueV3 { +public: + static Result> parse(std::string const& key, std::string const& modID, matjson::Value const& json) { + auto res = std::make_shared(); + auto root = checkJson(json, "PositionValue"); + res->parseBaseProperties(key, modID, root); + root.checkUnknownKeys(); + return root.ok(std::static_pointer_cast(res)); + } + SettingNodeV3* createNode(float width) override; +}; + + +template <> +struct geode::SettingTypeForValueType { + using SettingType = PositionValue; +}; + +class PositionNode : public SettingValueNodeV3 { +protected: + CCMenuItemToggler* m_tlBtn; + CCMenuItemToggler* m_trBtn; + CCMenuItemToggler* m_blBtn; + CCMenuItemToggler* m_brBtn; + bool init(std::shared_ptr setting, float width); + void updateState(CCNode* invoker) override { + SettingValueNodeV3::updateState(invoker); + } + void onCornerClick(PositionEnum value) { + m_tlBtn->toggle(true); + m_trBtn->toggle(true); + m_blBtn->toggle(true); + m_brBtn->toggle(true); + this->setValue(value, nullptr); + }; + void onResetToDefault() override { + m_tlBtn->toggle(true); + m_trBtn->toggle(true); + m_blBtn->toggle(true); + m_brBtn->toggle(false); + this->setValue(PositionEnum::BottomRight, nullptr); + } +public: + static PositionNode* create(std::shared_ptr setting, float width) { + auto ret = new PositionNode(); + if (ret && ret->init(setting, width)) { + ret->autorelease(); + return ret; + } + CC_SAFE_DELETE(ret); + return nullptr; + } +}; diff --git a/src/modules/settings/Test.cpp b/src/modules/settings/Test.cpp new file mode 100644 index 0000000..7901827 --- /dev/null +++ b/src/modules/settings/Test.cpp @@ -0,0 +1,157 @@ +#include +#include "../../include/RateEvent.hpp" + +using namespace geode::prelude; + +/* + --- Test --- +*/ + +int cycleTypes = -1; + +class TestValue : public SettingV3 { +public: + static Result> parse(std::string const& key, std::string const& modID, matjson::Value const& json) { + auto res = std::make_shared(); + auto root = checkJson(json, "TestValue"); + res->init(key, modID, root); + res->parseNameAndDescription(root); + res->parseEnableIf(root); + root.checkUnknownKeys(); + return root.ok(std::static_pointer_cast(res)); + } + + bool load(matjson::Value const& json) override { + return true; + } + bool save(matjson::Value& json) const override { + return true; + } + bool isDefaultValue() const override { + return true; + } + void reset() override {} + SettingNodeV3* createNode(float width) override; +}; + +class TestNode : public SettingNodeV3 { +protected: + bool init(std::shared_ptr setting, float width) { + if (!SettingNodeV3::init(setting, width)) + return false; + this->setContentSize({ width, 35.f }); + getButtonMenu()->setContentWidth(width); + Build::create("Test", "bigFont.fnt").scale(0.6f).parentAtPos(getButtonMenu(), Anchor::Left, {42, 0}); + Build::createSpriteName("GJ_playBtn2_001.png").scale(0.4f).intoMenuItem([]() { + auto scene = CCDirector::sharedDirector()->getRunningScene(); + cycleTypes = cycleTypes + 1; + if (cycleTypes > 4) cycleTypes = 0; + bool newRate = Mod::get()->getSettingValue("newRate"); + bool daily = Mod::get()->getSettingValue("daily"); + bool weekly = Mod::get()->getSettingValue("weekly"); + if (!newRate && cycleTypes == 0) cycleTypes = 1; + if (!daily && cycleTypes == 1) cycleTypes = 2; + if (!weekly && cycleTypes == 2) cycleTypes = 3; + if (!newRate && !daily && !weekly) { + cycleTypes = 5; + } + EventData data; + data.type = EventType::Rate; + data.rate = 1; + data.coins = 3; + data.verified_coins = true; + data.level_creator = "by RobTop"; + //{'demon': 1, 'type': 1, 'starsum': 6, 'stars': 10, 'rate': 1, 'title': 'BRAINPOWER Let the base kick!', 'level_name': 'O-oooooooooo AAAAE-A-A-I-A-U-', 'level_creator': ' JO-oooooooooooo AAE-O-A-A-U-U-A- E-eee-ee-eee AAAAE-A-E-I-E-A- JO-ooo-oo-oo-oo EEEEO-A-AAA-AAAA', 'sprite': 'GJ_square01.png'} + switch (cycleTypes) { + case 0: // new rate + data.title = "New Rated Level !"; + data.stars = 1; + data.starsum = 10; + data.level_name = "Stereo Madness"; + break; + case 1: // daily + data.title = "New Daily Level !"; + data.type = EventType::Daily; + data.stars = 9; + data.starsum = 40; + data.level_name = "Cycles"; + break; + case 2: // weekly + data.title = "New Weekly Level !"; + data.demon = true; + data.type = EventType::Weekly; + data.stars = 14; + data.starsum = 7; + data.level_name = "Theory of Everything 2"; + data.sprite = "GJ_square05.png"; + break; + case 3: // Legendary rating test + data.title = "New Rated Level !"; + data.stars = 3; + data.starsum = 20; + data.level_name = "Oh no it's happening"; + data.level_creator = "by ..."; + data.rate = 3; + break; + case 4: // Mythic rating test + data.title = "New Rated Level !"; + data.stars = 100; + data.starsum = 20; + data.type = EventType::Event; + data.level_name = "FIRE IN THE HOLE!"; + data.level_creator = "by GD Community"; + data.rate = 4; + break; + case 5: // in case the user disables everything + data.title = "New Rated Level !"; + data.demon = true; + data.stars = 2; + data.starsum = 6; + data.level_name = "Back On Track"; + data.rate = 1; + break; + default: // not possible + data.title = "hi there hxd user, ghidra user or ida user. (or hi RobTop) Here's a little easter egg for you :)"; + data.demon = true; + data.stars = 14; + data.starsum = 7; + data.sprite = "This will crash! :D"; + break; + } + GDUtils::Events::RateEvent::emit(data); + }).parentAtPos(getButtonMenu(), Anchor::Right, {-15, 0}); + getButtonMenu()->updateLayout(); + getNameLabel()->setVisible(false); + return true; + } + void onCommit() override {} + void onResetToDefault() override {} + +public: + bool hasUncommittedChanges() const override { + return false; + } + bool hasNonDefaultValue() const override { + return false; + } + static TestNode* create(std::shared_ptr setting, float width) { + auto ret = new TestNode(); + if (ret && ret->init(setting, width)) { + ret->autorelease(); + return ret; + } + CC_SAFE_DELETE(ret); + return nullptr; + } + std::shared_ptr getSetting() const { + return std::static_pointer_cast(SettingNodeV3::getSetting()); + } +}; + +SettingNodeV3* TestValue::createNode(float width) { + return TestNode::create(static_pointer_cast(shared_from_this()), width); +} + +$execute { + (void)Mod::get()->registerCustomSettingType("test-notification", &TestValue::parse); +} diff --git a/src/network/AMQClient.cpp b/src/network/AMQClient.cpp new file mode 100644 index 0000000..06512ad --- /dev/null +++ b/src/network/AMQClient.cpp @@ -0,0 +1,301 @@ +#include "AMQClient.hpp" +#include "../../include/RateEvent.hpp" + +bool show_connected = false; +std::queue dataQueue; +static std::optional> s_tx; + +void AMQT::setTx(arc::mpsc::Sender tx) { + s_tx = std::move(tx); +} + +bool AMQT::sendHeartbeat() { + auto now = std::chrono::steady_clock::now(); + auto lastDuration = std::chrono::duration_cast(now - m_lastHeartbeatTime).count(); + // every 10 seconds + if (lastDuration >= 10) { + std::lock_guard lock(m_mutex); + if (isConnected()) { + // because WHY CANT I USE amqp_heartbeat_send!?!? we will decide to manually construct it... + amqp_frame_t frame; + frame.channel = 0; // or 1? idk... amqp_socket.c says 0 + frame.frame_type = AMQP_FRAME_HEARTBEAT; + auto res = amqp_send_frame(m_connection, &frame); + if (AMQP_STATUS_OK != res) { + log::warn("Failed to send heartbeat: {}", amqp_error_string2(res)); + return false; + } else { + //log::debug("Sent heartbeat!"); + m_lastHeartbeatTime = now; + return true; + } + } + } + return true; +} + +std::string AMQReplyToString(amqp_response_type_enum val) { + switch (val) { + case AMQP_RESPONSE_NONE: + default: + return "AMQP_RESPONSE_NONE"; + case AMQP_RESPONSE_NORMAL: + return "AMQP_RESPONSE_NORMAL"; + case AMQP_RESPONSE_LIBRARY_EXCEPTION: + return "AMQP_RESPONSE_LIBRARY_EXCEPTION"; + case AMQP_RESPONSE_SERVER_EXCEPTION: + return "AMQP_RESPONSE_SERVER_EXCEPTION"; + } +} +std::string AMQErrorToString(amqp_rpc_reply_t reply) { + std::string errorStr; + switch (reply.reply_type) { + case AMQP_RESPONSE_NONE: errorStr = "No response"; break; + case AMQP_RESPONSE_LIBRARY_EXCEPTION: errorStr = amqp_error_string2(reply.library_error); break; + case AMQP_RESPONSE_SERVER_EXCEPTION: + if (reply.reply.id == AMQP_CONNECTION_CLOSE_METHOD) { + amqp_connection_close_t* m = (amqp_connection_close_t*) reply.reply.decoded; + errorStr = (char*)m->reply_text.bytes; + } else { + errorStr = "Unknown Error"; + } + break; + case AMQP_RESPONSE_NORMAL: break; + } + return fmt::format("{} ({})", errorStr, AMQReplyToString(reply.reply_type)); +} +void AMQT::setupChannel() { + bool showPastNotifs = false; + std::string queueName = fmt::format("amqp-queue-{}", client_id); + { + amqp_channel_open(m_connection, 1); + auto reply = amqp_get_rpc_reply(m_connection); + if (reply.reply_type != AMQP_RESPONSE_NORMAL) { + log::error("Error opening channel: {}", AMQErrorToString(reply)); + return; + } + } + // https://stackoverflow.com/questions/72237234/declare-a-queue-with-x-max-length-programmatically-using-rabbitmq-c + amqp_queue_declare_ok_t *r; + if (showPastNotifs) { + // this is absolutely cursed + /*amqp_table_entry_t q_arg_n_entries[2]; + q_arg_n_entries[0] = (amqp_table_entry_t) { + .key = amqp_cstring_bytes("x-queue-type"), + .value = {.kind = AMQP_FIELD_KIND_UTF8, .value = {.bytes = amqp_cstring_bytes("classic")}} + }; + + //86400000 + // 2 days + q_arg_n_entries[1] = (amqp_table_entry_t) { + .key = amqp_cstring_bytes("x-expires"), + .value = {.kind = AMQP_FIELD_KIND_I32, .value = {.i32 = 172800000}} + }; + amqp_table_t q_arg_table = {.num_entries = 2, .entries = q_arg_n_entries};*/ + + amqp_table_entry_t q_arg_n_entries[1]; + // 1 day + q_arg_n_entries[0] = (amqp_table_entry_t) { + .key = amqp_cstring_bytes("x-expires"), + .value = {.kind = AMQP_FIELD_KIND_I32, .value = {.i32 = 86400000}} + }; + amqp_table_t q_arg_table = {.num_entries = 1, .entries = q_arg_n_entries}; + r = amqp_queue_declare( + m_connection, 1, + amqp_cstring_bytes(queueName.c_str()), + 0, 1, 0, 0, + q_arg_table + ); + } else { + amqp_queue_delete(m_connection, 1, amqp_cstring_bytes(queueName.c_str()), 0, 0); + amqp_get_rpc_reply(m_connection); + + // server-side safety net: if the TCP connection ever fails to close cleanly + // (so exclusive doesn't trigger deletion), the queue expires anyway. + // 1 hour, well above the heartbeat (10s), so this should never trigger in normal usage. + amqp_table_entry_t q_arg_entries[1]; + q_arg_entries[0] = (amqp_table_entry_t) { + .key = amqp_cstring_bytes("x-expires"), + .value = {.kind = AMQP_FIELD_KIND_I32, .value = {.i32 = 3600000}} + }; + amqp_table_t q_arg_table = {.num_entries = 1, .entries = q_arg_entries}; + + r = amqp_queue_declare( + m_connection, 1, + amqp_cstring_bytes(queueName.c_str()), + 0, 0, 1, 1, + q_arg_table + ); + } + { + auto reply = amqp_get_rpc_reply(m_connection); + if (reply.reply_type != AMQP_RESPONSE_NORMAL) { + log::error("Error declaring queue: {}", AMQErrorToString(reply)); + return; + } + } + amqp_bytes_t queueBytes = amqp_bytes_malloc_dup(r->queue); + if (queueBytes.bytes == NULL) { + log::error("Couldn't copy queue name (Out of memory?)"); + return; + } + { + amqp_queue_bind(m_connection, 1, + queueBytes, amqp_cstring_bytes("amq.topic"), + amqp_cstring_bytes("rate.#"), amqp_empty_table + ); + auto reply = amqp_get_rpc_reply(m_connection); + if (reply.reply_type != AMQP_RESPONSE_NORMAL) { + log::error("Error binding queue: {}", AMQErrorToString(reply)); + return; + } + } + { + auto res = amqp_basic_consume(m_connection, 1, queueBytes, amqp_empty_bytes, 0, 1, 0, amqp_empty_table); + auto reply = amqp_get_rpc_reply(m_connection); + + if (reply.reply_type != AMQP_RESPONSE_NORMAL) { + log::error("Error consuming in queue: {}", AMQErrorToString(reply)); + return; + } + if (res) { + std::string data((char*)res->consumer_tag.bytes, res->consumer_tag.len); + GDUtils::Events::OnServerConnect().send(true); + log::info("Subscribed to Rate Notifications! (Consumer Tag: {})", data); + } + } + + bool forceReconnection = false; + auto lastReconnectTime = std::chrono::steady_clock::now(); + + struct timeval timeout = {10, 0}; + + while (isConnected()) { + // this is just an extra so we're sure that we're always connected + if (!sendHeartbeat()) { + log::error("Couldn't send heartbeat, disconnecting..."); + break; + } + if (forceReconnection) { + auto now = std::chrono::steady_clock::now(); + auto lastDuration = std::chrono::duration_cast(now - lastReconnectTime).count(); + if (lastDuration >= 600) { + log::info("Forcing a reconnection..."); + break; + } + } + amqp_envelope_t envelope; + amqp_maybe_release_buffers(m_connection); + auto ret = amqp_consume_message(m_connection, &envelope, &timeout, 0); + if (AMQP_RESPONSE_NORMAL != ret.reply_type) { + if (AMQP_RESPONSE_LIBRARY_EXCEPTION == ret.reply_type && AMQP_STATUS_HEARTBEAT_TIMEOUT == ret.library_error) { + log::error("Heartbeat failed, initiating a reconnection!"); + break; + } else if (AMQP_RESPONSE_LIBRARY_EXCEPTION == ret.reply_type && AMQP_STATUS_UNEXPECTED_STATE == ret.library_error) { + amqp_frame_t frame; + if (AMQP_STATUS_OK != amqp_simple_wait_frame(m_connection, &frame)) { + log::error("Failed to wait for frame after unexpected state: {}", AMQErrorToString(ret)); + break; + } + if (AMQP_FRAME_METHOD == frame.frame_type) { + if (frame.payload.method.id == AMQP_BASIC_ACK_METHOD) continue; + if (frame.payload.method.id == AMQP_BASIC_RETURN_METHOD) { + { + log::info("Got frame payload, re-reading message based on channel..."); + amqp_message_t message; + ret = amqp_read_message(m_connection, frame.channel, &message, 0); + if (AMQP_RESPONSE_NORMAL != ret.reply_type) { + log::error("Error reading returned message: {}", AMQErrorToString(ret)); + break; + } + std::string data((char*)message.body.bytes, message.body.len); + if (s_tx) { + (void)s_tx->trySend(std::move(data)); + } + amqp_destroy_message(&message); + } + continue; + } else { + log::error("(Frame ID: {}) Error consuming message: {}", frame.payload.method.id, AMQErrorToString(ret)); + break; + } + } else { + log::error("Response wasn't normal! {}", AMQErrorToString(ret)); + } + } else if (AMQP_RESPONSE_LIBRARY_EXCEPTION == ret.reply_type && AMQP_STATUS_TIMEOUT == ret.library_error) { + // honestly how has no one gotten this issue!? + continue; + } else { + log::error("Error consuming message: {}", AMQErrorToString(ret)); + break; + } + } else { + log::info("call rate event"); + std::string data((char*)envelope.message.body.bytes, envelope.message.body.len); + if (s_tx) { + (void)s_tx->trySend(std::move(data)); + } + amqp_destroy_envelope(&envelope); + } + } + GDUtils::Events::OnServerConnect().send(false); + m_connected = false; + m_cv.notify_all(); +} + +void AMQT::connect() { + m_remainingAttempts++; + while (m_remainingAttempts-- > 0) { + log::info("Starting AMQP..."); + if (m_remainingAttempts != MAX_RECONNECT_ATTEMPTS) { + int currentAttempt = MAX_RECONNECT_ATTEMPTS - m_remainingAttempts + 1; + int delayMs = 3000 * std::pow(2, currentAttempt - 1); + log::warn("Disconnected from server. Attempting to reconnect... ({} left, reconnecting in {} seconds)", m_remainingAttempts, (float)((delayMs / 1000.F))); + std::this_thread::sleep_for(std::chrono::milliseconds(delayMs)); + } + m_connection = amqp_new_connection(); + amqp_socket_t* socket = amqp_tcp_socket_new(m_connection); + if (!socket) { + log::error("Couldn't create TCP connection"); + continue; + } + int status; + status = amqp_socket_open(socket, AMQ_HOST, AMQ_PORT); + if (status != AMQP_STATUS_OK) { + log::error("Error opening socket! {}", amqp_error_string2(status)); + continue; + } + if (socket && m_connection) { + // heartbeat every 10 seconds! + amqp_rpc_reply_t reply = amqp_login(m_connection, "/", 0, 131072, 10, AMQP_SASL_METHOD_PLAIN, AMQ_USER, AMQ_PASS); + if (reply.reply_type != AMQP_RESPONSE_NORMAL) { + const char* errorStr = nullptr; + log::error("Couldn't login to AMQP server! {}", AMQErrorToString(reply)); + continue; + } + m_connected = true; + setupChannel(); + disconnect(); + } + } + log::error("Maximum reconnection attempts reached, cannot reconnect. Restart the game to reconnect to the MQTT server."); +} +bool AMQT::genConnected() { + return show_connected; +} +void AMQT::setGenConnected(bool value) { + show_connected = value; +} +std::queue AMQT::getQueue() { + return dataQueue; +} +std::string AMQT::getQueueFrontPop() { + std::string value = std::move(dataQueue.front()); + dataQueue.pop(); + return value; +} +void AMQT::sendToTx(const std::string data) { + if (s_tx) { + (void)s_tx->trySend(std::move(data)); + } +} diff --git a/src/network/AMQClient.hpp b/src/network/AMQClient.hpp new file mode 100644 index 0000000..415bbf0 --- /dev/null +++ b/src/network/AMQClient.hpp @@ -0,0 +1,55 @@ +#pragma once +#include +#ifdef GEODE_IS_WINDOWS // stop the dumb compiler errors! +#include +#include +//#include +#endif +#include +#include +#include +#include +#include + +class AMQT { + private: + amqp_connection_state_t m_connection; + amqp_socket_t* m_socket; + std::string client_id; + + std::atomic m_remainingAttempts = {MAX_RECONNECT_ATTEMPTS}; + std::atomic m_connected{false}; + + std::mutex m_mutex; + std::condition_variable m_cv; + + std::chrono::steady_clock::time_point m_lastActivityTime; + std::chrono::steady_clock::time_point m_lastHeartbeatTime; + + public: + AMQT(const std::string& client_id) : client_id(std::move(client_id)), m_lastActivityTime(std::chrono::steady_clock::now()), m_lastHeartbeatTime(m_lastActivityTime) {}; + void updateActivity() { + m_lastActivityTime = std::chrono::steady_clock::now(); + } + // since the current heartbeat does NOT work!! + bool sendHeartbeat(); + bool isConnected() { + return m_connected.load(); + } + void setupChannel(); + void connect(); + void disconnect() { + if (m_connection) { + m_connected = false; + amqp_destroy_connection(m_connection); + m_connection = nullptr; + } + } + static bool genConnected(); + static void setGenConnected(bool value); + static std::queue getQueue(); + static std::string getQueueFrontPop(); + static void sendToTx(const std::string); + static void setTx(arc::mpsc::Sender tx); +}; + diff --git a/src/ui/DownloadPopup.cpp b/src/ui/DownloadPopup.cpp new file mode 100644 index 0000000..81e74d2 --- /dev/null +++ b/src/ui/DownloadPopup.cpp @@ -0,0 +1,81 @@ +#include "DownloadPopup.hpp" +#ifndef GEODE_IS_MACOS // unfortunately figs video player not supported on mac becuase opengl32 doesnt want to compile correctly koeirjnfioewbnfejwf +#include +#include +#include +#include + +// ------ +// 204 = MAX +// 0 = MIN +bool RobProgressBar::init() { // on purpose im not even providing any params because why would we!?; + progressBar->setPosition({3, 8}); + progressBar->setAnchorPoint({ 0, 0.5 }); + progressBar->setTextureRect(CCRect(0, 0, 204, 8)); + ccTexParams params = { GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT }; // tf is this nonsense mat + progressBar->getTexture()->setTexParameters(¶ms); + this->addChild(outerBg); + progressBar->setZOrder(-1); + outerBg->addChild(progressBar); + return true; +} + +void RobProgressBar::setProgress(float percentage) { + this->m_pPercentage = percentage; + float realPercentage = (204/100) * this->m_pPercentage; // "Result of integer division used in a floating point" ok i know clangd warnings wow + progressBar->setTextureRect(CCRect(0, 0, realPercentage, 8)); +} + +RobProgressBar* RobProgressBar::create() { + auto ret = new RobProgressBar(); + if (ret && ret->init()) { + ret->autorelease(); + return ret; + } + delete ret; + return nullptr; +} + +bool DownloadPopup::init(const char* url, std::filesystem::path destination, std::function callback) { + if (!Popup::init(300.f, 150.f)) return false; + Build::create("Downloading...", "bigFont.fnt").scale(0.8f).parentAtPos(m_mainLayer, Anchor::Top, {0, -25}); + + loading_circle->setParentLayer(this); + loading_circle->setScale(0.675f); + loading_circle->show(); + m_progressBar = RobProgressBar::create(); + m_progressBar->setProgress(0.0F); + m_mainLayer->addChildAtPosition(m_progressBar, Anchor::Center, {0, -30}); + + Build::create("Do not close this menu while the file is being downloaded.", "chatFont.fnt").scale(.5f).alignment(cocos2d::kCCTextAlignmentCenter).parentAtPos(m_mainLayer, Anchor::Bottom, {0, 18}); + geode::utils::web::WebRequest req = web::WebRequest(); + req.onProgress([this](web::WebProgress const& progress) { + if (!progress.downloadProgress().has_value()) return; + log::debug("Progress({},{},{})", progress.downloadProgress(), progress.downloaded(), progress.downloadTotal()); + auto scene = CCDirector::sharedDirector()->getRunningScene(); + if (m_progressBar != nullptr) { + m_progressBar->setProgress(progress.downloadProgress().value()); + } + }); + m_listener.spawn( + req.get(url), + [this, destination, callback](web::WebResponse value) { + (void)geode::utils::file::writeBinarySafe(destination, value.data()); + onClose(nullptr); + callback(); + } + ); + return true; +} + +DownloadPopup* DownloadPopup::create(const char* url, std::filesystem::path destination, std::function callback) { + auto ret = new DownloadPopup(); + if (ret && ret->init(url, destination, callback)) { + ret->autorelease(); + return ret; + } + delete ret; + return nullptr; +} +// below is copied from the gdr mod lol +#endif diff --git a/src/ui/DownloadPopup.hpp b/src/ui/DownloadPopup.hpp new file mode 100644 index 0000000..b268bdb --- /dev/null +++ b/src/ui/DownloadPopup.hpp @@ -0,0 +1,30 @@ +#pragma once +// windows only because i cant get this to work, actually im too lazy +#ifndef GEODE_IS_MACOS +#include +using namespace geode::prelude; +class RobProgressBar : public CCNode { + protected: + float m_pPercentage = 0; + CCSprite* outerBg = CCSprite::create("slidergroove.png"); + CCSprite* progressBar = CCSprite::create("sliderBar.png"); + bool init(); + public: + void testProgressbar(); + virtual void setProgress(float percentage); + static RobProgressBar* create(); +}; +class DownloadPopup : public geode::Popup { + protected: + bool init(const char* url, std::filesystem::path, std::function); + RobProgressBar* m_progressBar; + LoadingCircle* loading_circle = LoadingCircle::create(); + async::TaskHolder m_listener; + public: + static DownloadPopup* create(const char* url, std::filesystem::path, std::function); //, cocos2d::SEL_MenuHandler callback + virtual void onClose(CCObject*) override { + m_listener.cancel(); + Popup::onClose(nullptr); + } +}; +#endif diff --git a/src/ui/EventInfoPopup.cpp b/src/ui/EventInfoPopup.cpp new file mode 100644 index 0000000..e669d0d --- /dev/null +++ b/src/ui/EventInfoPopup.cpp @@ -0,0 +1,69 @@ +#include "EventInfoPopup.hpp" + +EventInfoPopup* EventInfoPopup::create() { + auto ret = new EventInfoPopup(); + if (ret && ret->init()) { + ret->autorelease(); + return ret; + } + delete ret; + return nullptr; +} + +arc::Future> EventInfoPopup::reqTask() { + ARC_FRAME(); + auto req = web::WebRequest(); + req.header("Cache-Control", "no-cache").header("Pragma", "no-cache"); + + std::string URL = "https://clarifygdps.com/gdutils/event_info/image_banner.png?randome=" + std::to_string(static_cast(time(nullptr))); + //std::string URL = "https://clarifygdps.com/gdutils/event_info/image_banner_oldNCS.png"; + + auto response = co_await req.get(URL); + + if (response.ok()) { + co_return Ok(std::move(response).data()); + } + + co_return Err(response.errorMessage()); +} + +bool EventInfoPopup::init() { + if (!Popup::init(400.0f, 225.0f, "GJ_square02.png")) return false; + + m_sprite = LazySprite::create(this->m_mainLayer->getContentSize()); + m_sprite->setScale(.55f); + this->m_mainLayer->addChildAtPosition(m_sprite, Anchor::Center); + + m_sprite->setLoadCallback([this](Result<> res) { + this->imageCreationFinished(std::move(res)); + }); + + m_listener.spawn(EventInfoPopup::reqTask(), [this](auto result) { + onFetch(std::move(result)); + }); + return true; +} + +void EventInfoPopup::imageCreationFinished(Result<> res) { + if (!res) { + log::debug("Failed to load image: {}", res.err().value_or(std::string{})); + this->onDownloadFail(); + return; + } +} + +void EventInfoPopup::onDownloadFail() { + auto failLabel = CCLabelBMFont::create("No event banner found.", "bigFont.fnt", 0.0f, kCCTextAlignmentCenter); + m_sprite->cancelLoad(); + failLabel->setScale(0.7f); + this->m_mainLayer->addChildAtPosition(failLabel, Anchor::Center); +} + +void EventInfoPopup::onFetch(Result result) { + if (result.isErr()) { + log::error("Error when fetching image: {}", result.unwrapErr()); + this->onDownloadFail(); + } else { + m_sprite->loadFromData(std::move(result).unwrap()); + } +} diff --git a/src/ui/EventInfoPopup.hpp b/src/ui/EventInfoPopup.hpp new file mode 100644 index 0000000..bc71d64 --- /dev/null +++ b/src/ui/EventInfoPopup.hpp @@ -0,0 +1,22 @@ +#pragma once +#include + +class EventInfoPopup : public Popup { + protected: + LazySprite* m_sprite; + async::TaskHolder> m_listener; + Ref m_image; + + bool init() override; + void loadPage(); + void imageCreationFinished(Result<>); + void onDownloadFail(); + arc::Future> reqTask(); + void onFetch(Result); + public: + static EventInfoPopup* create(); + virtual void onClose(CCObject*) override { + m_listener.cancel(); + Popup::onClose(nullptr); + } +}; diff --git a/src/OldBorder.cpp b/src/ui/OldBorder.cpp similarity index 58% rename from src/OldBorder.cpp rename to src/ui/OldBorder.cpp index 937e2b6..5b4060b 100644 --- a/src/OldBorder.cpp +++ b/src/ui/OldBorder.cpp @@ -5,11 +5,9 @@ OldBorder* OldBorder::create(CCNode* node, const ccColor4B& backgroundColor, con if (instance && instance->init(node, backgroundColor, size)) { instance->autorelease(); - return instance; } else { - CC_SAFE_DELETE(instance); - + delete instance; return nullptr; } } @@ -24,50 +22,32 @@ bool OldBorder::init(CCNode* node, const ccColor4B& backgroundColor, const CCSiz if (!this->initWithColor(backgroundColor)) { return false; } - - CCScale9Sprite* OldBorder = CCScale9Sprite::create("inverseborder.png"_spr); - CCLayer* content = CCLayer::create(); - - OldBorder->setID("border_sprite"_spr); - OldBorder->setAnchorPoint({ 0, 0 }); - OldBorder->setPosition({ 0, 0 }); - OldBorder->setZOrder(1); - content->setID("border_content"_spr); - content->setContentSize(size); - this->addChild(OldBorder); - this->addChild(content); - + Build::create("inverseborder.png"_spr) + .id("border_sprite"_spr) + .anchorPoint({0,0}) + .pos(0,0) + .zOrder(1) + .parent(this) + .store(m_inverseBorder); + Build::create().id("border_content"_spr).contentSize(size).parent(this).store(m_content); if (node != nullptr) { this->setNode(node); } - this->setSize(size); - return true; } -void OldBorder::setPadding(const CCPoint& padding) { - this->setPadding(padding.x, padding.y); -} void OldBorder::setPadding(float x, float y) { this->setPaddingX(x); this->setPaddingY(y); } -void OldBorder::setPadding(float padding) { - this->setPadding(padding, padding); -} - void OldBorder::setPaddingX(float x) { this->setPaddingLeft(x); this->setPaddingRight(x); } -OldBorder::Padding OldBorder::getPadding() { - return m_padding; -} - float OldBorder::getPaddingX() { return (m_padding.left + m_padding.right) / 2; } @@ -87,9 +67,6 @@ void OldBorder::setPaddingTop(float top) { this->updatePadding(); } -float OldBorder::getPaddingTop() { - return m_padding.top; -} void OldBorder::setPaddingRight(float right) { m_padding.right = right; @@ -97,30 +74,17 @@ void OldBorder::setPaddingRight(float right) { this->updatePadding(); } -float OldBorder::getPaddingRight() { - return m_padding.right; -} - void OldBorder::setPaddingBottom(float bottom) { m_padding.bottom = bottom; this->updatePadding(); } -float OldBorder::getPaddingBottom() { - return m_padding.bottom; -} - void OldBorder::setPaddingLeft(float left) { m_padding.left = left; this->updatePadding(); } - -float OldBorder::getPaddingLeft() { - return m_padding.left; -} - void OldBorder::setBackgroundColor(const ccColor4B& color) { this->setColor({ color.r, color.g, color.b }); this->setOpacity(color.a); @@ -131,40 +95,25 @@ ccColor4B OldBorder::getBackgroundColor() { } void OldBorder::setNode(CCNode* node) { - CCNode* content = this->getChildByID("border_content"_spr); - // Can't assume an ID as the node is a user input and may have its ID changed - if (CCNode* oldNode = cocos::getChild(content, 0)) { + if (CCNode* oldNode = m_content->getChildByType(0)) { // Not going to mess with releasing the node, I'll leave that to the user oldNode->removeFromParent(); } - - content->addChild(node); - + m_content->addChild(node); this->updatePadding(); } -CCNode* OldBorder::getNode() { - if (CCNode* node = cocos::getChild(this->getChildByID("border_content"_spr), 0)) { - return node; - } else { - return nullptr; - } -} - void OldBorder::setSize(const CCSize& size) { this->setContentSize(size); - this->getChildByID("border_sprite"_spr)->setContentSize(size); - this->getChildByID("border_content"_spr)->setContentSize(size); + m_inverseBorder->setContentSize(size); + m_content->setContentSize(size); this->updatePadding(); } void OldBorder::updatePadding() { - if (CCNode* node = this->getNode()) { - CCSize size = this->getContentSize(); - - node->setAnchorPoint({ 0, 0 }); - node->setPosition({ m_padding.left, m_padding.bottom }); - node->setContentSize(size - ccp(this->getPaddingX(), this->getPaddingY()) * 2); - } -} \ No newline at end of file + CCSize size = this->getContentSize(); + m_content->setAnchorPoint({ 0, 0 }); + m_content->setPosition({ m_padding.left, m_padding.bottom }); + m_content->setContentSize(size - ccp(this->getPaddingX(), this->getPaddingY()) * 2); +} diff --git a/src/OldBorder.hpp b/src/ui/OldBorder.hpp similarity index 68% rename from src/OldBorder.hpp rename to src/ui/OldBorder.hpp index 05b43b9..d1dd8e3 100644 --- a/src/OldBorder.hpp +++ b/src/ui/OldBorder.hpp @@ -1,5 +1,5 @@ #pragma once -#include "includes.h" +#include class OldBorder : public cocos2d::CCLayerColor { public: @@ -12,33 +12,33 @@ class OldBorder : public cocos2d::CCLayerColor { static OldBorder* create(cocos2d::CCNode* node, const cocos2d::ccColor4B& backgroundColor, const cocos2d::CCSize& size = { 0, 0 }, const cocos2d::CCPoint& padding = { 0, 0 }); - void setPadding(const cocos2d::CCPoint& padding); + void setPadding(const cocos2d::CCPoint& padding) { this->setPadding(padding.x, padding.y); } void setPadding(float x, float y); - void setPadding(float padding); - Padding getPadding(); + void setPadding(float padding) { this->setPadding(padding, padding); } + Padding getPadding() { return m_padding; } void setPaddingX(float x); float getPaddingX(); void setPaddingY(float y); float getPaddingY(); void setPaddingTop(float top); - float getPaddingTop(); + float getPaddingTop() { return m_padding.top; } void setPaddingRight(float right); - float getPaddingRight(); + float getPaddingRight() { return m_padding.right; } void setPaddingBottom(float bottom); - float getPaddingBottom(); + float getPaddingBottom() { return m_padding.bottom; } void setPaddingLeft(float left); - float getPaddingLeft(); + float getPaddingLeft() { return m_padding.left; } void setBackgroundColor(const cocos2d::ccColor4B& color); cocos2d::ccColor4B getBackgroundColor(); void setNode(CCNode* node); - CCNode* getNode(); void setSize(const cocos2d::CCSize& size); protected: Padding m_padding; - + CCLayer* m_content; + CCScale9Sprite* m_inverseBorder; OldBorder(const cocos2d::CCPoint& padding = { 0, 0 }); bool init(const cocos2d::ccColor4B& backgroundColor, const cocos2d::CCSize& size); bool init(CCNode* node, const cocos2d::ccColor4B& backgroundColor, const cocos2d::CCSize& size); private: void updatePadding(); -}; \ No newline at end of file +}; diff --git a/src/ui/SearchUserLayer.cpp b/src/ui/SearchUserLayer.cpp new file mode 100644 index 0000000..db8884d --- /dev/null +++ b/src/ui/SearchUserLayer.cpp @@ -0,0 +1,14 @@ +#include "SearchUserLayer.hpp" + +bool SearchUserLayer::init(FriendsProfilePage* layer) { + //if (!Popup::init(260.f, 60.f)) return false; + if (!Popup::init(260.f, 120.f)) return false; + m_friendPage = layer; + input_username->setMaxCharCount(20); + input_username->setPlaceholder(""); + m_buttonMenu->addChildAtPosition(input_username, Anchor::Center, {0, 10}); + Build::create("Search", 60, true, "bigFont.fnt", "GJ_button_01.png", 30, .5F).intoMenuItem([this]() { + onValidate(); + }).parentAtPos(m_buttonMenu, Anchor::Center, {0, -35}); + return true; +} diff --git a/src/ui/SearchUserLayer.hpp b/src/ui/SearchUserLayer.hpp new file mode 100644 index 0000000..2b6f243 --- /dev/null +++ b/src/ui/SearchUserLayer.hpp @@ -0,0 +1,22 @@ +#pragma once +#include + +class SearchUserLayer : public Popup { + protected: + WeakRef m_friendPage; + + bool init(FriendsProfilePage*); + void onValidate(); + public: + TextInput* input_username = TextInput::create(200.0F, "Username", "bigFont.fnt"); + static SearchUserLayer* create(FriendsProfilePage* layer) { + auto ret = new SearchUserLayer(); + if (ret->init(layer)) { + ret->autorelease(); + return ret; + } + delete ret; + return nullptr; + } +}; + diff --git a/src/Settings/CreditsBetaMenu.cpp b/src/ui/credits/CreditsBetaMenu.cpp similarity index 96% rename from src/Settings/CreditsBetaMenu.cpp rename to src/ui/credits/CreditsBetaMenu.cpp index c62c6f3..6c65d14 100644 --- a/src/Settings/CreditsBetaMenu.cpp +++ b/src/ui/credits/CreditsBetaMenu.cpp @@ -1,5 +1,6 @@ -#include "CreditsBetaMenu.h" -#include "../includes.h" +#include "CreditsBetaMenu.hpp" +#include +using namespace geode::prelude; struct CreditData { std::string username; @@ -42,7 +43,8 @@ std::vector users = { auto paginated = misc::paginate(users, 6); -bool CreditsBetaMenu::setup() { +bool CreditsBetaMenu::init() { + if (!Popup::init(300.f, 200.f)) return false; auto winSize = cocos2d::CCDirector::sharedDirector()->getWinSize(); auto title = CCLabelBMFont::create("Beta Credits", "bigFont.fnt"); diff --git a/src/Settings/CreditsBetaMenu.h b/src/ui/credits/CreditsBetaMenu.hpp similarity index 74% rename from src/Settings/CreditsBetaMenu.h rename to src/ui/credits/CreditsBetaMenu.hpp index 16f5b7c..1883611 100644 --- a/src/Settings/CreditsBetaMenu.h +++ b/src/ui/credits/CreditsBetaMenu.hpp @@ -1,14 +1,14 @@ #pragma once -class CreditsBetaMenu : public geode::Popup<> { +class CreditsBetaMenu : public geode::Popup { protected: cocos2d::CCNode* m_section; uint8_t m_currentPage = 0; - bool setup() override; + bool init(); public: void updatePage(); static CreditsBetaMenu* create() { auto ret = new CreditsBetaMenu(); - if (ret->initAnchored(300.f, 200.f)) { + if (ret->init()) { ret->autorelease(); return ret; } diff --git a/src/Settings/CreditsMenu.cpp b/src/ui/credits/CreditsMenu.cpp similarity index 96% rename from src/Settings/CreditsMenu.cpp rename to src/ui/credits/CreditsMenu.cpp index 3db0ca1..5d7b38c 100644 --- a/src/Settings/CreditsMenu.cpp +++ b/src/ui/credits/CreditsMenu.cpp @@ -1,8 +1,8 @@ -#include "CreditsMenu.h" -#include "Geode/utils/web.hpp" +#include "CreditsMenu.hpp" using namespace geode::prelude; -bool CreditsMenu::setup() { +bool CreditsMenu::init() { + if (!Popup::init(300.f, 200.f)) return false; auto title = CCLabelBMFont::create("Credits", "bigFont.fnt"); title->setScale(0.8f); m_mainLayer->addChildAtPosition(title, Anchor::Top, {0, -25}); diff --git a/src/Settings/CreditsMenu.h b/src/ui/credits/CreditsMenu.hpp similarity index 67% rename from src/Settings/CreditsMenu.h rename to src/ui/credits/CreditsMenu.hpp index 03de185..0c9c48b 100644 --- a/src/Settings/CreditsMenu.h +++ b/src/ui/credits/CreditsMenu.hpp @@ -1,11 +1,11 @@ #pragma once -class CreditsMenu : public geode::Popup<> { +class CreditsMenu : public geode::Popup { protected: - bool setup() override; + bool init(); public: static CreditsMenu* create() { auto ret = new CreditsMenu(); - if (ret->initAnchored(300.f, 200.f)) { + if (ret->init()) { ret->autorelease(); return ret; } diff --git a/src/ui/moreleaderboards/LevelHelper.hpp b/src/ui/moreleaderboards/LevelHelper.hpp new file mode 100644 index 0000000..c44fc81 --- /dev/null +++ b/src/ui/moreleaderboards/LevelHelper.hpp @@ -0,0 +1,159 @@ +#pragma once +#include + +#define STAR_EXP 5 +#define MOON_EXP 5 +#define DIAMOND_EXP 2 +#define GOLD_COIN_EXP 100 +#define USER_COIN_EXP 20 +#define DEMON_EXP 75 +#define CP_EXP 5000 + +class LevelHelper { +public: + inline static int calculateTotalEXP(GJUserScore* score) { + int totalEXP = 0; + totalEXP += (STAR_EXP * score->m_stars); + totalEXP += (MOON_EXP * score->m_moons); + totalEXP += (DIAMOND_EXP * score->m_diamonds); + totalEXP += (GOLD_COIN_EXP * score->m_secretCoins); + totalEXP += (USER_COIN_EXP * score->m_userCoins); + totalEXP += (DEMON_EXP * score->m_demons); + totalEXP += (CP_EXP * score->m_creatorPoints); + return totalEXP; + } + + inline static int getEXPRequiredForLevel(int level) { + return (50 * (level * level) + (50 * level)); + } + + inline static int getLevelFromEXP(int exp) { + return (sqrt(2 * exp + 25) - 5) / 10.0; + } +}; + +class SpriteHelper { +public: + inline static CCSprite* createFullSprite(int currentLevel) { + auto badgeSprite = SpriteHelper::getBadgeFromLevel(currentLevel); + badgeSprite->setID("itzkiba.better_progression/tier-badge"); + badgeSprite->setZOrder(10); + + auto badgeLabel = CCLabelBMFont::create(std::to_string(currentLevel).c_str(), "bigFont.fnt"); + badgeLabel->setZOrder(11); + badgeLabel->setScale((currentLevel >= 100 ? 0.3 : 0.4)); + badgeLabel->setPosition({badgeSprite->getContentSize().width / 2, badgeSprite->getContentSize().height / 2 + 1.f}); + badgeSprite->addChild(badgeLabel); + + auto badgeShadow = CCSprite::createWithSpriteFrameName("itzkiba.better_progression/shadow.png"); + badgeShadow->setZOrder(-5); + badgeShadow->setScale(0.9); + badgeShadow->setPosition({badgeSprite->getContentSize().width / 2, badgeSprite->getContentSize().height / 2}); + badgeShadow->setOpacity(100); + badgeSprite->addChild(badgeShadow); + + auto badgeGlow = SpriteHelper::getGlowFromLevel(currentLevel); + if (badgeGlow != nullptr && currentLevel <= 350) { + badgeGlow->setZOrder(-3); + badgeGlow->setPosition({badgeSprite->getContentSize().width / 2, badgeSprite->getContentSize().height / 2}); + badgeGlow->setScaleX(0.975); + badgeGlow->setScaleY(0.95); + badgeSprite->addChild(badgeGlow); + + ccBlendFunc blending = {GL_ONE, GL_ONE}; + badgeGlow->setBlendFunc(blending); + + if (currentLevel >= 200 && currentLevel <= 224) badgeGlow->setColor({255, 156, 110}); + if (currentLevel >= 225 && currentLevel <= 249) badgeGlow->setColor({90, 255, 148}); + if (currentLevel >= 250 && currentLevel <= 274) badgeGlow->setColor({65, 239, 255}); + if (currentLevel >= 275 && currentLevel <= 299) badgeGlow->setColor({245, 108, 255}); + + auto fadein = CCEaseSineInOut::create(CCFadeTo::create(0.9f, 50)); + auto fadeout = CCEaseSineInOut::create(CCFadeTo::create(0.9f, 255)); + auto sequence = CCSequence::create(fadein, fadeout, nullptr); + badgeGlow->runAction(CCRepeatForever::create(sequence)); + } + return badgeSprite; + } + + inline static CCSprite* getBadgeFromLevel(int level) { + const char* frame = "itzkiba.better_progression/tier0_0.png"; + if (level >= 5 && level <= 9) frame = "itzkiba.better_progression/tier0_1.png"; + if (level >= 10 && level <= 14) frame = "itzkiba.better_progression/tier0_2.png"; + if (level >= 15 && level <= 19) frame = "itzkiba.better_progression/tier0_3.png"; + if (level >= 20 && level <= 24) frame = "itzkiba.better_progression/tier0_4.png"; + if (level >= 25 && level <= 29) frame = "itzkiba.better_progression/tier1_0.png"; + if (level >= 30 && level <= 34) frame = "itzkiba.better_progression/tier1_1.png"; + if (level >= 35 && level <= 39) frame = "itzkiba.better_progression/tier1_2.png"; + if (level >= 40 && level <= 44) frame = "itzkiba.better_progression/tier1_3.png"; + if (level >= 45 && level <= 49) frame = "itzkiba.better_progression/tier1_4.png"; + if (level >= 50 && level <= 54) frame = "itzkiba.better_progression/tier2_0.png"; + if (level >= 55 && level <= 59) frame = "itzkiba.better_progression/tier2_1.png"; + if (level >= 60 && level <= 64) frame = "itzkiba.better_progression/tier2_2.png"; + if (level >= 65 && level <= 69) frame = "itzkiba.better_progression/tier2_3.png"; + if (level >= 70 && level <= 74) frame = "itzkiba.better_progression/tier2_4.png"; + if (level >= 75 && level <= 79) frame = "itzkiba.better_progression/tier3_0.png"; + if (level >= 80 && level <= 84) frame = "itzkiba.better_progression/tier3_1.png"; + if (level >= 85 && level <= 89) frame = "itzkiba.better_progression/tier3_2.png"; + if (level >= 90 && level <= 94) frame = "itzkiba.better_progression/tier3_3.png"; + if (level >= 95 && level <= 99) frame = "itzkiba.better_progression/tier3_4.png"; + if (level >= 100 && level <= 104) frame = "itzkiba.better_progression/tier4_0.png"; + if (level >= 105 && level <= 109) frame = "itzkiba.better_progression/tier4_1.png"; + if (level >= 110 && level <= 114) frame = "itzkiba.better_progression/tier4_2.png"; + if (level >= 115 && level <= 119) frame = "itzkiba.better_progression/tier4_3.png"; + if (level >= 120 && level <= 124) frame = "itzkiba.better_progression/tier4_4.png"; + if (level >= 125 && level <= 129) frame = "itzkiba.better_progression/tier5_0.png"; + if (level >= 130 && level <= 134) frame = "itzkiba.better_progression/tier5_1.png"; + if (level >= 135 && level <= 139) frame = "itzkiba.better_progression/tier5_2.png"; + if (level >= 140 && level <= 144) frame = "itzkiba.better_progression/tier5_3.png"; + if (level >= 145 && level <= 149) frame = "itzkiba.better_progression/tier5_4.png"; + if (level >= 150 && level <= 154) frame = "itzkiba.better_progression/tier6_0.png"; + if (level >= 155 && level <= 159) frame = "itzkiba.better_progression/tier6_1.png"; + if (level >= 160 && level <= 164) frame = "itzkiba.better_progression/tier6_2.png"; + if (level >= 165 && level <= 169) frame = "itzkiba.better_progression/tier6_3.png"; + if (level >= 170 && level <= 174) frame = "itzkiba.better_progression/tier6_4.png"; + if (level >= 175 && level <= 179) frame = "itzkiba.better_progression/tier7_0.png"; + if (level >= 180 && level <= 184) frame = "itzkiba.better_progression/tier7_1.png"; + if (level >= 185 && level <= 189) frame = "itzkiba.better_progression/tier7_2.png"; + if (level >= 190 && level <= 194) frame = "itzkiba.better_progression/tier7_3.png"; + if (level >= 195 && level <= 199) frame = "itzkiba.better_progression/tier7_4.png"; + if (level >= 200 && level <= 204) frame = "itzkiba.better_progression/tier8_0.png"; + if (level >= 205 && level <= 209) frame = "itzkiba.better_progression/tier8_1.png"; + if (level >= 210 && level <= 214) frame = "itzkiba.better_progression/tier8_2.png"; + if (level >= 215 && level <= 219) frame = "itzkiba.better_progression/tier8_3.png"; + if (level >= 220 && level <= 224) frame = "itzkiba.better_progression/tier8_4.png"; + if (level >= 225 && level <= 229) frame = "itzkiba.better_progression/tier9_0.png"; + if (level >= 230 && level <= 234) frame = "itzkiba.better_progression/tier9_1.png"; + if (level >= 235 && level <= 239) frame = "itzkiba.better_progression/tier9_2.png"; + if (level >= 240 && level <= 244) frame = "itzkiba.better_progression/tier9_3.png"; + if (level >= 245 && level <= 249) frame = "itzkiba.better_progression/tier9_4.png"; + if (level >= 250 && level <= 254) frame = "itzkiba.better_progression/tier10_0.png"; + if (level >= 255 && level <= 259) frame = "itzkiba.better_progression/tier10_1.png"; + if (level >= 260 && level <= 264) frame = "itzkiba.better_progression/tier10_2.png"; + if (level >= 265 && level <= 269) frame = "itzkiba.better_progression/tier10_3.png"; + if (level >= 270 && level <= 274) frame = "itzkiba.better_progression/tier10_4.png"; + if (level >= 275 && level <= 279) frame = "itzkiba.better_progression/tier11_0.png"; + if (level >= 280 && level <= 284) frame = "itzkiba.better_progression/tier11_1.png"; + if (level >= 285 && level <= 289) frame = "itzkiba.better_progression/tier11_2.png"; + if (level >= 290 && level <= 294) frame = "itzkiba.better_progression/tier11_3.png"; + if (level >= 295 && level <= 299) frame = "itzkiba.better_progression/tier11_4.png"; + if (level >= 300 && level <= 349) frame = "itzkiba.better_progression/tier12.png"; + return CCSprite::createWithSpriteFrameName(frame); + } + + inline static CCSprite* getGlowFromLevel(int level) { + if (level < 200) return nullptr; + int mod = level % 25; + int tier = mod / 5; + const char* frames[] = { + "itzkiba.better_progression/glow_0.png", + "itzkiba.better_progression/glow_1.png", + "itzkiba.better_progression/glow_2.png", + "itzkiba.better_progression/glow_3.png", + "itzkiba.better_progression/glow_4.png", + }; + if (level >= 300 && level <= 349) return CCSprite::createWithSpriteFrameName("itzkiba.better_progression/glow_4.png"); + if (level >= 350) return nullptr; + return CCSprite::createWithSpriteFrameName(frames[tier]); + } +}; diff --git a/src/ui/moreleaderboards/MoreLeaderboards.cpp b/src/ui/moreleaderboards/MoreLeaderboards.cpp new file mode 100644 index 0000000..f7452fa --- /dev/null +++ b/src/ui/moreleaderboards/MoreLeaderboards.cpp @@ -0,0 +1,863 @@ +#include "MoreLeaderboards.hpp" +#include "tabs/TabButton.hpp" +#include +#include + +StatsListType MoreLeaderboards::g_tab = StatsListType::Stars; +bool MoreLeaderboards::modFilter = false; +int MoreLeaderboards::modFilterType = 0; +std::string MoreLeaderboards::username = ""; +int MoreLeaderboards::scroll_int = 0; +std::string MoreLeaderboards::data_response_moreLB = ""; + +static int page = 0; +static int start_count = 0; +static int end_count = 0; +static int total_count = 0; + +std::vector MoreLeaderboards::getWords(std::string s, std::string delim) { + std::vector res; + std::string token = ""; + for (int i = 0; i < (int)s.size(); i++) { + bool flag = true; + for (int j = 0; j < (int)delim.size(); j++) { + if (s[i + j] != delim[j]) flag = false; + } + if (flag) { + if (token.size() > 0) { + res.push_back(token); + token = ""; + i += delim.size() - 1; + } + } else { + token += s[i]; + } + } + res.push_back(token); + return res; +} + +class SearchUserLBLayer : public Popup { +protected: + bool init(MoreLeaderboards* layer) { + if (!Popup::init(260.f, 75.f)) return false; + m_layer = layer; + input_username->setMaxCharCount(20); + input_username->setPlaceholder(""); + m_buttonMenu->addChildAtPosition(input_username, Anchor::Center, {0, 10}); + + Build::create("Search", 60, true, "bigFont.fnt", "GJ_button_01.png", 30, .5F) + .intoMenuItem([this]() { + if (this->m_layer->loading) return; + MoreLeaderboards::username = input_username->getString(); + this->m_layer->changeTabPage(); + this->m_layer->onTab(nullptr); + Popup::onClose(nullptr); + }).parentAtPos(m_buttonMenu, Anchor::Center, {0, -30}); + + if (MoreLeaderboards::username != "") { + input_username->setString(MoreLeaderboards::username); + Build::createSpriteName("GJ_deleteBtn_001.png").scale(.45f) + .intoMenuItem([this]() { + MoreLeaderboards::username = ""; + MoreLeaderboards::scroll_int = 0; + input_username->setString(""); + this->m_layer->changeTabPage(); + this->m_layer->onTab(nullptr); + Popup::onClose(nullptr); + }).parentAtPos(m_buttonMenu, Anchor::Right, {-17, 0}); + } + return true; + } + +public: + MoreLeaderboards* m_layer = nullptr; + TextInput* input_username = TextInput::create(200.0F, "Username", "bigFont.fnt"); + + static SearchUserLBLayer* create(MoreLeaderboards* layer) { + auto ret = new SearchUserLBLayer(); + if (ret->init(layer)) { + ret->autorelease(); + return ret; + } + delete ret; + return nullptr; + } +}; + +CCDictionary* MoreLeaderboards::responseToDict(const std::string& response) { + auto dict = CCDictionary::create(); + std::stringstream responseStream(response); + std::string currentKey; + std::string keyID; + std::string playerID; + std::string username; + std::string accountID; + + GameLevelManager* glm = GameLevelManager::sharedState(); + unsigned int i = 0; + while (getline(responseStream, currentKey, ':')) { + if (i % 2 == 0) { + keyID = currentKey; + } else { + if (keyID == "2") playerID = currentKey; + else if (keyID == "16") accountID = currentKey; + else if (keyID == "1") username = currentKey; + dict->setObject(CCString::create(currentKey.c_str()), keyID); + } + i++; + } + if (playerID.length() > 0 && username.length() > 0 && accountID.length() > 0) { + glm->storeUserName( + numFromString(playerID).unwrapOrDefault(), + numFromString(accountID).unwrapOrDefault(), + username + ); + } + return dict; +} + +void MoreLeaderboards::onMoreLeaderboards(CCObject*) { + auto scene = CCScene::create(); + scene->addChild(MoreLeaderboards::create("more")); + CCDirector::sharedDirector()->pushScene(CCTransitionFade::create(0.5, scene)); +} + +void MoreLeaderboards::onModsList(CCObject*) { + auto scene = CCScene::create(); + scene->addChild(MoreLeaderboards::create("mods")); + CCDirector::sharedDirector()->pushScene(CCTransitionFade::create(0.5, scene)); +} + +void MoreLeaderboards::onRegion(CCObject*) { + SelectRegion::scene([this](std::string id) { + country_id = id; + if (loading) return; + loading = true; + loading_circle = LoadingCircle::create(); + loading_circle->setZOrder(25); + loading_circle->setParentLayer(this); + loading_circle->show(); + + if (displayedData) { + displayedData->release(); + displayedData = cocos2d::CCArray::create(); + displayedData->retain(); + } + page = 0; + if (loading) { + startLoadingMore(); + loadPageMore(); + } + resetInfos(); + }); +} + +void MoreLeaderboards::onInfo(CCObject*) { + FLAlertLayer::create( + nullptr, + "More Leaderboards", + R"text( +More Leaderboards is a feature that allows you to view more leaderboards than the ones in the game. +You can view leaderboards for Diamonds, User Coins, Demons, Moons, and Creators Points of people that are registered on Updated Leaderboards project. + +Thanks to ChiefWoof & the Helper team for providing the data for this feature! + )text", + "OK", nullptr, 400.0f + )->show(); +} + +void MoreLeaderboards::onLBInfo(CCObject*) { + geode::createQuickPopup( + "Submit your user stats", + R"text( +You can submit your user stats to the Updated Leaderboards team by joining their Discord server and following the instructions right there. + )text", + "OK", "Discord Server", + [](auto, bool btn2) { + if (btn2) web::openLinkInBrowser("https://discord.gg/mZnDm886sR"); + } + ); +} + +MoreLeaderboards* MoreLeaderboards::create(std::string type) { + auto pRet = new MoreLeaderboards(); + SelectRegionCell::country_id = "NAN"; + if (pRet && pRet->init(type)) { + pRet->autorelease(); + return pRet; + } + CC_SAFE_DELETE(pRet); + return nullptr; +} + +bool MoreLeaderboards::init(std::string type) { + auto director = cocos2d::CCDirector::sharedDirector(); + auto size = director->getWinSize(); + + displayedData = cocos2d::CCArray::create(); + displayedData->retain(); + + auto background = CCSprite::create("GJ_gradientBG.png"); + auto backgroundSize = background->getContentSize(); + background->setScaleX(size.width / backgroundSize.width); + background->setScaleY(size.height / backgroundSize.height); + background->setAnchorPoint({0, 0}); + background->setColor(Mod::get()->getSettingValue("background")); + background->setZOrder(-1); + this->addChild(background); + + auto corner_left = CCSprite::createWithSpriteFrameName("GJ_sideArt_001.png"); + auto corner_right = CCSprite::createWithSpriteFrameName("GJ_sideArt_001.png"); + corner_right->setRotation(-90); + corner_left->setPosition({35, 35}); + corner_right->setPosition({size.width - 35, 35}); + this->addChild(corner_left); + this->addChild(corner_right); + + auto backBtn = CCMenuItemSpriteExtra::create( + CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png"), + this, menu_selector(MoreLeaderboards::backButton) + ); + auto backMenu = CCMenu::create(); + backMenu->addChild(backBtn); + backMenu->setPosition({25, size.height - 25}); + this->addChild(backMenu); + + if (type == "more") { + auto menu_region = CCMenu::create(); + + auto regionSpr = CCSprite::create("earth_btn.png"_spr); + regionSpr->setScale(.8f); + auto regionBtn = CCMenuItemSpriteExtra::create( + regionSpr, this, menu_selector(MoreLeaderboards::onRegion) + ); + regionBtn->setPosition(239, -52); + menu_region->addChild(regionBtn); + + auto infoBtn = CCMenuItemSpriteExtra::create( + CCSprite::createWithSpriteFrameName("GJ_infoIcon_001.png"), + this, menu_selector(MoreLeaderboards::onInfo) + ); + infoBtn->setPosition(-239, -120); + menu_region->addChild(infoBtn); + + auto lbBtn = CCMenuItemSpriteExtra::create( + CCSprite::createWithSpriteFrameName("GJ_levelLeaderboardBtn_001.png"), + this, menu_selector(MoreLeaderboards::onLBInfo) + ); + lbBtn->setPosition(-239, -57); + menu_region->addChild(lbBtn); + + this->addChild(menu_region); + + tab_page = 0; + +#ifndef GEODE_IS_IOS + m_tabsGradientNode = CCClippingNode::create(); +#else + m_tabsGradientNode = CCNode::create(); +#endif + m_tabsGradientNode->setContentSize(this->getContentSize()); + m_tabsGradientNode->setAnchorPoint({0.5f, 0.5f}); + m_tabsGradientNode->ignoreAnchorPointForPosition(true); + m_tabsGradientNode->setZOrder(0); + m_tabsGradientNode->setScale(0.8f); +#ifndef GEODE_IS_IOS + m_tabsGradientNode->setInverted(false); + m_tabsGradientNode->setAlphaThreshold(0.7f); +#endif + + m_tabsGradientSprite = CCSprite::create("tab-gradient.png"_spr); + m_tabsGradientNode->addChild(m_tabsGradientSprite); + + m_tabsGradientStencil = CCSprite::create("tab-gradient-mask.png"_spr); + m_tabsGradientStencil->setAnchorPoint({0.f, 0.f}); + m_tabsGradientStencil->setColor({172, 255, 67}); + m_tabsGradientStencil->setZOrder(1); + m_tabsGradientStencil->setScale(0.8f); + +#ifndef GEODE_IS_IOS + m_tabsGradientNode->setStencil(m_tabsGradientStencil); +#endif + + this->addChild(m_tabsGradientNode); + this->addChild(m_tabsGradientStencil); + + changeTabPage(); + this->onTab(nullptr); + } else if (type == "mods") { + loading_circle = LoadingCircle::create(); + loading_circle->setZOrder(25); + loading_circle->setParentLayer(this); + loading_circle->show(); + startLoadingMods(); + loadPageMods(); + } + + setTouchEnabled(true); + setKeypadEnabled(true); + return true; +} + +void MoreLeaderboards::backButton(cocos2d::CCObject*) { + MoreLeaderboards::data_response_moreLB = ""; + MoreLeaderboards::g_tab = StatsListType::Stars; + MoreLeaderboards::username = ""; + MoreLeaderboards::scroll_int = 0; + MoreLeaderboards::modFilter = false; + MoreLeaderboards::modFilterType = 0; + cocos2d::CCDirector::sharedDirector()->popSceneWithTransition(0.5F, cocos2d::PopTransition::kPopTransitionFade); +} + +void MoreLeaderboards::keyBackClicked() { + backButton(CCNode::create()); +} + +void MoreLeaderboards::fadeLoadingCircle() { + if (loading_circle == nullptr) return; + loading_circle->fadeAndRemove(); +} + +void MoreLeaderboards::handle_request_mods(std::string const& data) { + if (!displayedData) { displayedData = CCArray::create(); displayedData->retain(); } + if (data != "-1") { + displayedData = CCArray::create(); + std::vector mods = getWords(data, "|"); + while (mods.size() > 0) { + CCDictionary* modDict = CCDictionary::create(); + modDict->setObject(CCString::create(mods[0]), "modstring"); + displayedData->addObject(modDict); + mods.erase(mods.begin()); + } + } + loadPageMods(); +} + +void MoreLeaderboards::startLoadingMods() { + this->retain(); + m_listener.spawn( + web::WebRequest().get("https://clarifygdps.com/gdutils/modslist.php"), + [this](web::WebResponse value) { + if (value.ok()) handle_request_mods(value.string().unwrapOrDefault()); + fadeLoadingCircle(); + this->release(); + } + ); +} + +void MoreLeaderboards::loadPageMods() { + if (listLayer != nullptr) listLayer->removeFromParentAndCleanup(true); + auto winSize = CCDirector::sharedDirector()->getWinSize(); + leaderboardView = MoreLeaderboardsListView::create(displayedData, 356.f, 220.f); + listLayer = GJListLayer::create(leaderboardView, "GD Moderators", {191, 114, 62, 255}, 356.f, 220.f, 0); + listLayer->setPosition(winSize / 2 - listLayer->getScaledContentSize() / 2 - CCPoint(0, 5)); + addChild(listLayer); +} + +static std::string tabTypeToString(StatsListType t) { + switch (t) { + case StatsListType::Diamonds: return "diamonds"; + case StatsListType::UserCoins: return "ucoins"; + case StatsListType::Demons: return "demons"; + case StatsListType::Moons: return "moons"; + case StatsListType::Creators: return "cp"; + case StatsListType::Stars: return "stars"; + case StatsListType::classicDemonsEasy: return "classicDemonsEasy"; + case StatsListType::classicDemonsMedium: return "classicDemonsMedium"; + case StatsListType::classicDemonsHard: return "classicDemonsHard"; + case StatsListType::classicDemonsInsane: return "classicDemonsInsane"; + case StatsListType::classicDemonsExtreme: return "classicDemonsExtreme"; + case StatsListType::platformerDemonsEasy: return "platformerDemonsEasy"; + case StatsListType::platformerDemonsMedium: return "platformerDemonsMedium"; + case StatsListType::platformerDemonsHard: return "platformerDemonsHard"; + case StatsListType::platformerDemonsInsane: return "platformerDemonsInsane"; + case StatsListType::platformerDemonsExtreme: return "platformerDemonsExtreme"; + case StatsListType::BetterProgression: return "betterProgression"; + case StatsListType::Pointercrate: return "pointercratePoints"; + } + return "stars"; +} + +void MoreLeaderboards::startLoadingLeaderboard() { + this->retain(); + auto type = tabTypeToString(MoreLeaderboards::g_tab); + m_lbListener.spawn( + web::WebRequest() + .param("type", type) + .param("page", page) + .param("country", country_id) + .param("username", username) + .param("mod", (modFilter ? "1" : "0")) + .param("modFilter", modFilterType) + .param("version", "1.0") + .get("https://clarifygdps.com/gdutils/moreleaderboards.php"), + [this](web::WebResponse value) { + loading = false; + auto scene = CCDirector::sharedDirector()->getRunningScene(); + auto layer = scene->getChildren()->objectAtIndex(0); + if (layer == nullptr || typeinfo_cast(layer) == nullptr) { + this->release(); + return; + } + if (!value.ok()) { + fadeLoadingCircle(); + geode::createQuickPopup("Error", + "An error occured while sending a request on our server. Please try again later.", + "OK", nullptr, + [this](auto, bool btn2) { + if (!btn2) { MoreLeaderboards::g_tab = StatsListType::Stars; keyBackClicked(); } + } + ); + this->release(); + return; + } + auto data = value.string().unwrap(); + if (data == "-1" || data.length() < 2) { + fadeLoadingCircle(); + geode::createQuickPopup("Error", + "An error occured while sending a request on our server. Please try again later.", + "OK", nullptr, + [this](auto, bool btn2) { + if (!btn2) { MoreLeaderboards::g_tab = StatsListType::Stars; keyBackClicked(); } + } + ); + this->release(); + return; + } + if (data == "-2") { + fadeLoadingCircle(); + FLAlertLayer::create(nullptr, "Error", + "User not found : " + MoreLeaderboards::username, + "OK", nullptr, 200.0F + )->show(); + MoreLeaderboards::scroll_int = 0; + loadTabPageButtons(); + this->release(); + return; + } + handle_request_more(data); + fadeLoadingCircle(); + this->release(); + } + ); +} + +void MoreLeaderboards::startLoadingMore() { + if (data_region != "") { + startLoadingLeaderboard(); + return; + } + this->retain(); + m_listener.spawn( + web::WebRequest().get("https://clarifygdps.com/gdutils/moreleaderboards_region.php"), + [this](web::WebResponse value) { + if (!value.ok()) { + loading = false; + auto scene = CCDirector::sharedDirector()->getRunningScene(); + auto layer = scene->getChildren()->objectAtIndex(0); + if (layer == nullptr || typeinfo_cast(layer) == nullptr) { + this->release(); + return; + } + fadeLoadingCircle(); + geode::createQuickPopup("Error", + "An error occured while sending a request on our server. Please try again later.", + "OK", nullptr, + [this](auto, bool btn2) { + if (!btn2) { MoreLeaderboards::g_tab = StatsListType::Stars; keyBackClicked(); } + } + ); + this->release(); + return; + } + auto data = value.string().unwrap(); + if (data != "-1") { + data_region = data; + SelectRegion::displayedData = MoreLeaderboards::getWords(data, "|"); + } + this->release(); + startLoadingLeaderboard(); + } + ); +} + +void MoreLeaderboards::handle_request_more(std::string const& data) { + if (!displayedData) { displayedData = CCArray::create(); displayedData->retain(); } + if (data != "-1") { + data_response_moreLB = data; + displayedData = CCArray::create(); + std::vector dataString = getWords(data, "#"); + std::vector users = getWords(dataString[0], "|"); + std::vector data_page = getWords(dataString[1], "|"); + + while (users.size() > 0) { + auto score = GJUserScore::create(MoreLeaderboards::responseToDict(users[0])); + displayedData->addObject(score); + users.erase(users.begin()); + } + + int id = 0; + while (data_page.size() > 0) { + int val = numFromString(data_page[0]).unwrapOrDefault(); + if (id == 0) start_count = val; + else if (id == 1) end_count = val; + else if (id == 2) total_count = val; + else if (id == 3) page = val; + else if (id == 4 && val != 0) MoreLeaderboards::scroll_int = val; + id++; + data_page.erase(data_page.begin()); + } + } + loadPageMore(); + loadPageStats(); +} + +void MoreLeaderboards::loadPageMore() { + if (listLayer != nullptr) listLayer->removeFromParentAndCleanup(true); + auto winSize = CCDirector::sharedDirector()->getWinSize(); + leaderboardViewScore = CustomListView::create(displayedData, nullptr, 220.f, 356.f, 0, BoomListType::Score, 0.0F); + listLayer = GJListLayer::create(leaderboardViewScore, nullptr, {191, 114, 62, 255}, 356.f, 220.f, 0); + listLayer->setZOrder(31); + listLayer->setPosition(winSize / 2 - listLayer->getScaledContentSize() / 2 - CCPoint(0, 5)); + addChild(listLayer); + + if (MoreLeaderboards::scroll_int != 0) { + listLayer->m_listView->m_tableView->scrollLayer((float)-INT_MAX); + listLayer->m_listView->m_tableView->scrollLayer(MoreLeaderboards::scroll_int); + } +} + +void MoreLeaderboards::onSearch(CCObject*) { + SearchUserLBLayer::create(this)->show(); +} + +void MoreLeaderboards::loadPageStats() { + auto winSize = CCDirector::sharedDirector()->getWinSize(); + + if (page_label != nullptr) page_label->removeFromParentAndCleanup(true); + if (auto n = this->getChildByIDRecursive("menu_label")) n->removeFromParentAndCleanup(true); + if (auto n = this->getChildByIDRecursive("menu_page")) n->removeFromParentAndCleanup(true); + + CCMenu* menu_label = CCMenu::create(); + menu_label->setID("menu_label"); + menu_label->setLayout( + RowLayout::create()->setAxisAlignment(AxisAlignment::Center)->setGap(10.f) + ); + menu_label->setPosition({winSize.width / 2, 12.f}); + menu_label->setContentSize({300.f, 7.f}); + + std::string fmt = fmt::format("Top {} - {} of {}", start_count, end_count, total_count); + page_label = CCLabelBMFont::create(fmt.c_str(), "goldFont.fnt"); + page_label->setZOrder(40); + page_label->setLayoutOptions( + AxisLayoutOptions::create()->setAutoScale(true)->setScaleLimits(0, 0.7F)->setScalePriority(1) + ); + menu_label->addChild(page_label); + + trophy = CCSprite::createWithSpriteFrameName("rankIcon_top10_001.png"); + trophy->setScale(.3f); + trophy->setPosition(CCPoint{-5.f, 0.f} - page_label->getScaledContentSize().width); + menu_label->addChild(trophy); + + addChild(menu_label); + menu_label->updateLayout(); + + CCMenu* menu = CCMenu::create(); + menu->setID("menu_page"); + + if (page_left != nullptr) page_left->removeFromParentAndCleanup(true); + if (page_right != nullptr) page_right->removeFromParentAndCleanup(true); + + if (page > 0) { + page_left = CCMenuItemSpriteExtra::create( + CCSprite::createWithSpriteFrameName("GJ_arrow_02_001.png"), + this, menu_selector(MoreLeaderboards::onPageLeft) + ); + page_left->setPosition(-220, 0); + menu->addChild(page_left); + } + + if (end_count < total_count) { + auto sprite = CCSprite::createWithSpriteFrameName("GJ_arrow_02_001.png"); + sprite->setFlipX(true); + page_right = CCMenuItemSpriteExtra::create( + sprite, this, menu_selector(MoreLeaderboards::onPageRight) + ); + page_right->setPosition(220, 0); + menu->addChild(page_right); + } + + addChild(menu); + loadTabPageButtons(); +} + +void MoreLeaderboards::loadTabPageButtons() { + if (tab_page_left != nullptr) { tab_page_left->removeFromParentAndCleanup(true); tab_page_left = nullptr; } + if (tab_page_right != nullptr) { tab_page_right->removeFromParentAndCleanup(true); tab_page_right = nullptr; } + if (m_search != nullptr) { m_search->removeFromParentAndCleanup(true); m_search = nullptr; } + if (mod_filter_btn != nullptr) { mod_filter_btn->removeFromParentAndCleanup(true); mod_filter_btn = nullptr; } + if (mod_filter_type_btn != nullptr) { mod_filter_type_btn->removeFromParentAndCleanup(true); mod_filter_type_btn = nullptr; } + + if (tab_page > 0) { + auto spr = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); + spr->setScale(0.6f); + tab_page_left = CCMenuItemSpriteExtra::create(spr, this, menu_selector(MoreLeaderboards::onTabPageLeft)); + tab_page_left->setPosition(-184, 138); + m_menu->addChild(tab_page_left); + } + + if (tab_page < 2) { + auto spr = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); + spr->setScale(0.6f); + spr->setFlipX(true); + tab_page_right = CCMenuItemSpriteExtra::create(spr, this, menu_selector(MoreLeaderboards::onTabPageRight)); + tab_page_right->setPosition(184, 138); + m_menu->addChild(tab_page_right); + } + + m_search = CCMenuItemSpriteExtra::create( + CCSprite::createWithSpriteFrameName("gj_findBtn_001.png"), + this, menu_selector(MoreLeaderboards::onSearch) + ); + m_search->setPosition(239, 104); + m_menu->addChild(m_search); + + auto mod_filter_spr = CCSprite::createWithSpriteFrameName("modBadge_01_001.png"); + mod_filter_spr->setScale(1.4f); + if (!modFilter) mod_filter_spr->setColor({100, 100, 100}); + mod_filter_btn = CCMenuItemSpriteExtra::create( + mod_filter_spr, this, menu_selector(MoreLeaderboards::onModFilter) + ); + mod_filter_btn->setPosition(239.f, 69.f); + m_menu->addChild(mod_filter_btn); + + if (modFilter) { + CCSprite* mod_filter_type_spr; + switch (modFilterType) { + case 0: { + auto s1 = CCSprite::createWithSpriteFrameName("modBadge_01_001.png"); s1->setScale(1.2f); s1->setPosition({30, 21}); + auto s2 = CCSprite::createWithSpriteFrameName("modBadge_02_001.png"); s2->setScale(1.2f); s2->setPosition({10, 21}); + auto s3 = CCSprite::createWithSpriteFrameName("modBadge_03_001.png"); s3->setScale(1.2f); s3->setPosition({20, 11}); + mod_filter_type_spr = CCSprite::create(); + mod_filter_type_spr->addChild(s1); + mod_filter_type_spr->addChild(s2); + mod_filter_type_spr->addChild(s3); + mod_filter_type_spr->setContentSize({40, 40}); + break; + } + case 1: mod_filter_type_spr = CCSprite::createWithSpriteFrameName("modBadge_01_001.png"); mod_filter_type_spr->setScale(1.4f); break; + case 2: mod_filter_type_spr = CCSprite::createWithSpriteFrameName("modBadge_02_001.png"); mod_filter_type_spr->setScale(1.4f); break; + default: mod_filter_type_spr = CCSprite::createWithSpriteFrameName("modBadge_03_001.png"); mod_filter_type_spr->setScale(1.4f); break; + } + mod_filter_type_btn = CCMenuItemSpriteExtra::create( + mod_filter_type_spr, this, menu_selector(MoreLeaderboards::onModFilterType) + ); + mod_filter_type_btn->setPosition(239.f, 34.f); + m_menu->addChild(mod_filter_type_btn); + } +} + +void MoreLeaderboards::onTabPageLeft(CCObject*) { + if (loading) return; + tab_page--; + changeTabPage(); + page = 0; + this->onTab(nullptr); +} + +void MoreLeaderboards::onTabPageRight(CCObject*) { + if (loading) return; + tab_page++; + changeTabPage(); + page = 0; + this->onTab(nullptr); +} + +void MoreLeaderboards::onModFilter(CCObject*) { + if (loading) return; + modFilter = !modFilter; + modFilterType = 0; + page = 0; + this->onTab(nullptr); +} + +void MoreLeaderboards::onModFilterType(CCObject*) { + if (loading) return; + modFilterType = (modFilterType == 3) ? 0 : modFilterType + 1; + page = 0; + this->onTab(nullptr); +} + +void MoreLeaderboards::changeTabPage() { + if (m_search != nullptr) { m_search->removeFromParentAndCleanup(true); m_search = nullptr; } + if (m_tab1 != nullptr) { m_tab1->removeFromParentAndCleanup(true); m_tab1 = nullptr; } + if (m_tab2 != nullptr) { m_tab2->removeFromParentAndCleanup(true); m_tab2 = nullptr; } + if (m_tab3 != nullptr) { m_tab3->removeFromParentAndCleanup(true); m_tab3 = nullptr; } + if (m_tab4 != nullptr) { m_tab4->removeFromParentAndCleanup(true); m_tab4 = nullptr; } + if (m_tab5 != nullptr) { m_tab5->removeFromParentAndCleanup(true); m_tab5 = nullptr; } + if (m_tab6 != nullptr) { m_tab6->removeFromParentAndCleanup(true); m_tab6 = nullptr; } + + if (auto n = this->getChildByIDRecursive("menu_gdutils_buttons")) + n->removeFromParentAndCleanup(true); + tab_page_left = nullptr; + tab_page_right = nullptr; + mod_filter_btn = nullptr; + mod_filter_type_btn = nullptr; + + m_menu = CCMenu::create(); + m_menu->setID("menu_gdutils_buttons"); + m_menu->setZOrder(1); + + auto stars_sprite = CCSprite::createWithSpriteFrameName("star_small01_001.png"); + auto moons_sprite = CCSprite::createWithSpriteFrameName("moon_small01_001.png"); + auto diamond_sprite = CCSprite::createWithSpriteFrameName("diamond_small01_001.png"); + auto usercoins_sprite = CCSprite::createWithSpriteFrameName("GJ_coinsIcon2_001.png"); + auto demons_sprite = CCSprite::createWithSpriteFrameName("GJ_demonIcon_001.png"); + auto creators_sprite = CCSprite::createWithSpriteFrameName("GJ_hammerIcon_001.png"); + auto better_progression = CCSprite::create("better_progression.png"_spr); + auto pointercrate = CCSprite::createWithSpriteFrameName("diffIcon_06_btn_001.png"); + auto pointercrate_text = CCLabelBMFont::create("PC", "goldFont.fnt"); + pointercrate_text->setPosition(28, 0); + pointercrate_text->setScale(0.5f); + pointercrate->addChild(pointercrate_text); + + auto makeClassicSpr = [](const char* base) { + auto classic = CCSprite::createWithSpriteFrameName("star_small01_001.png"); + classic->setPositionX(30); classic->setScale(1.2f); + auto spr = CCSprite::createWithSpriteFrameName(base); + spr->addChild(classic); + return spr; + }; + auto makePlatformerSpr = [](const char* base) { + auto moon = CCSprite::createWithSpriteFrameName("moon_small01_001.png"); + moon->setPositionX(30); moon->setScale(1.2f); + auto spr = CCSprite::createWithSpriteFrameName(base); + spr->addChild(moon); + return spr; + }; + + auto addTab = [&](CCMenuItemToggler*& slot, CCNode* icon, StatsListType type, float x) { + slot = NewTabButton::create(TabBaseColor::Unselected, TabBaseColor::Selected, icon, this, menu_selector(MoreLeaderboards::onTab)); + slot->setPosition(x, 132); + slot->setTag(static_cast(type)); + slot->setZOrder(30); + slot->setScale(0.8f); + m_menu->addChild(slot); + }; + + switch (tab_page) { + case 0: + MoreLeaderboards::g_tab = StatsListType::Stars; + addTab(m_tab1, stars_sprite, StatsListType::Stars, -140.f); + addTab(m_tab2, moons_sprite, StatsListType::Moons, -86.f); + addTab(m_tab3, usercoins_sprite, StatsListType::UserCoins, -30.f); + addTab(m_tab4, demons_sprite, StatsListType::Demons, 26.f); + addTab(m_tab5, diamond_sprite, StatsListType::Diamonds, 82.f); + addTab(m_tab6, creators_sprite, StatsListType::Creators, 138.f); + break; + case 1: + if (geode::Loader::get()->isModLoaded("itzkiba.better_progression")) { + MoreLeaderboards::g_tab = StatsListType::BetterProgression; + addTab(m_tab1, better_progression, StatsListType::BetterProgression, -140.f); + } else { + MoreLeaderboards::g_tab = StatsListType::Pointercrate; + addTab(m_tab1, pointercrate, StatsListType::Pointercrate, -140.f); + } + addTab(m_tab2, makeClassicSpr("diffIcon_07_btn_001.png"), StatsListType::classicDemonsEasy, -86.f); + addTab(m_tab3, makeClassicSpr("diffIcon_08_btn_001.png"), StatsListType::classicDemonsMedium, -30.f); + addTab(m_tab4, makeClassicSpr("diffIcon_06_btn_001.png"), StatsListType::classicDemonsHard, 26.f); + addTab(m_tab5, makeClassicSpr("diffIcon_09_btn_001.png"), StatsListType::classicDemonsInsane, 82.f); + addTab(m_tab6, makeClassicSpr("diffIcon_10_btn_001.png"), StatsListType::classicDemonsExtreme, 138.f); + break; + case 2: + MoreLeaderboards::g_tab = StatsListType::platformerDemonsEasy; + addTab(m_tab1, makePlatformerSpr("diffIcon_07_btn_001.png"), StatsListType::platformerDemonsEasy, -140.f); + addTab(m_tab2, makePlatformerSpr("diffIcon_08_btn_001.png"), StatsListType::platformerDemonsMedium, -86.f); + addTab(m_tab3, makePlatformerSpr("diffIcon_06_btn_001.png"), StatsListType::platformerDemonsHard, -30.f); + addTab(m_tab4, makePlatformerSpr("diffIcon_09_btn_001.png"), StatsListType::platformerDemonsInsane, 26.f); + addTab(m_tab5, makePlatformerSpr("diffIcon_10_btn_001.png"), StatsListType::platformerDemonsExtreme, 82.f); + if (geode::Loader::get()->isModLoaded("itzkiba.better_progression")) + addTab(m_tab6, pointercrate, StatsListType::Pointercrate, 138.f); + break; + } + + this->addChild(m_menu); +} + +void MoreLeaderboards::onPageLeft(CCObject*) { + if (loading) return; + MoreLeaderboards::username = ""; + MoreLeaderboards::scroll_int = 0; + loading = true; + loading_circle = LoadingCircle::create(); + loading_circle->setParentLayer(this); + loading_circle->setZOrder(25); + loading_circle->show(); + if (displayedData) { displayedData->release(); displayedData = CCArray::create(); displayedData->retain(); } + page--; + resetInfos(); + if (loading) { startLoadingMore(); loadPageMore(); } +} + +void MoreLeaderboards::onPageRight(CCObject*) { + if (loading) return; + MoreLeaderboards::username = ""; + MoreLeaderboards::scroll_int = 0; + loading = true; + loading_circle = LoadingCircle::create(); + loading_circle->setZOrder(25); + loading_circle->setParentLayer(this); + loading_circle->show(); + if (displayedData) { displayedData->release(); displayedData = CCArray::create(); displayedData->retain(); } + page++; + resetInfos(); + if (loading) { startLoadingMore(); loadPageMore(); } +} + +void MoreLeaderboards::resetInfos() { + if (page_label != nullptr) { page_label->removeFromParentAndCleanup(true); page_label = nullptr; } + if (page_left != nullptr) { page_left->removeFromParentAndCleanup(true); page_left = nullptr; } + if (page_right != nullptr) { page_right->removeFromParentAndCleanup(true); page_right = nullptr; } + if (trophy != nullptr) { trophy->removeFromParentAndCleanup(true); trophy = nullptr; } + if (mod_filter_btn != nullptr) { mod_filter_btn->removeFromParentAndCleanup(true); mod_filter_btn = nullptr; } + if (mod_filter_type_btn != nullptr) { mod_filter_type_btn->removeFromParentAndCleanup(true); mod_filter_type_btn = nullptr; } +} + +void MoreLeaderboards::onTab(CCObject* pSender) { + if (loading) return; + loading = true; + + loading_circle = LoadingCircle::create(); + loading_circle->setZOrder(25); + loading_circle->setParentLayer(this); + loading_circle->show(); + + if (displayedData) { displayedData->release(); displayedData = CCArray::create(); displayedData->retain(); } + if (pSender) MoreLeaderboards::g_tab = static_cast(pSender->getTag()); + resetInfos(); + page = 0; + + auto toggleTab = [this](CCMenuItemToggler* member) { + auto isSelected = member->getTag() == static_cast(MoreLeaderboards::g_tab); + auto targetMenu = m_menu; + member->toggle(isSelected); + if (member->getParent() != targetMenu) { + member->retain(); + member->removeFromParent(); + targetMenu->addChild(member); + member->release(); + } + if (isSelected && m_tabsGradientStencil) + m_tabsGradientStencil->setPosition(member->m_onButton->convertToWorldSpace({0.f, 0.f})); + }; + + if (m_tab1) toggleTab(m_tab1); + if (m_tab2) toggleTab(m_tab2); + if (m_tab3) toggleTab(m_tab3); + if (m_tab4) toggleTab(m_tab4); + if (m_tab5) toggleTab(m_tab5); + if (m_tab6) toggleTab(m_tab6); + + if (loading) { startLoadingMore(); loadPageMore(); } +} diff --git a/src/ui/moreleaderboards/MoreLeaderboards.hpp b/src/ui/moreleaderboards/MoreLeaderboards.hpp new file mode 100644 index 0000000..284b869 --- /dev/null +++ b/src/ui/moreleaderboards/MoreLeaderboards.hpp @@ -0,0 +1,118 @@ +#pragma once +#include +#include +#include "mods/MoreLeaderboardsListView.hpp" +#include "region/SelectRegion.hpp" + +enum class StatsListType { + Stars, + Diamonds, + UserCoins, + Demons, + Moons, + Creators, + classicDemonsEasy, + classicDemonsMedium, + classicDemonsHard, + classicDemonsInsane, + classicDemonsExtreme, + platformerDemonsEasy, + platformerDemonsMedium, + platformerDemonsHard, + platformerDemonsInsane, + platformerDemonsExtreme, + BetterProgression, + Pointercrate +}; + +class MoreLeaderboards : public CCLayer { + MoreLeaderboardsListView* leaderboardView = nullptr; + CustomListView* leaderboardViewScore = nullptr; + GJListLayer* listLayer = nullptr; + LoadingCircle* loading_circle = nullptr; + cocos2d::CCArray* displayedData; + + CCLabelBMFont* page_label = nullptr; + CCMenuItemSpriteExtra* page_left = nullptr; + CCMenuItemSpriteExtra* page_right = nullptr; + CCMenuItemSpriteExtra* tab_page_left = nullptr; + CCMenuItemSpriteExtra* tab_page_right = nullptr; + CCMenuItemSpriteExtra* mod_filter_btn = nullptr; + CCMenuItemSpriteExtra* mod_filter_type_btn = nullptr; + CCSprite* trophy = nullptr; + + CCString* datas = nullptr; + std::string data_region = ""; + std::string country_id = "NAN"; + + CCMenu* m_menu; + CCMenuItemToggler* m_tab1; + CCMenuItemToggler* m_tab2; + CCMenuItemToggler* m_tab3; + CCMenuItemToggler* m_tab4; + CCMenuItemToggler* m_tab5; + CCMenuItemToggler* m_tab6; + int tab_page = 0; + + CCMenuItemSpriteExtra* m_search; + +#ifndef GEODE_IS_IOS + CCClippingNode* m_tabsGradientNode = nullptr; +#else + CCNode* m_tabsGradientNode = nullptr; +#endif + CCSprite* m_tabsGradientSprite = nullptr; + CCSprite* m_tabsGradientStencil = nullptr; + +protected: + virtual bool init(std::string type); + virtual void keyBackClicked(); + void startLoadingMods(); + void loadPageMods(); + void startLoadingMore(); + void loadPageMore(); + void loadPageStats(); + void resetInfos(); + +public: + static std::string data_response_moreLB; + static StatsListType g_tab; + static std::string username; + static int scroll_int; + static bool modFilter; + static int modFilterType; + bool loading = false; + + async::TaskHolder m_listener; + async::TaskHolder m_lbListener; + + void onMoreLeaderboards(CCObject*); + void onModsList(CCObject*); + void onRegion(CCObject*); + void onInfo(CCObject*); + void onLBInfo(CCObject*); + + void onTab(CCObject* pSender); + void onPageLeft(CCObject* pSender); + void onPageRight(CCObject* pSender); + + void loadTabPageButtons(); + void onTabPageLeft(CCObject* pSender); + void onTabPageRight(CCObject* pSender); + void onModFilter(CCObject* pSender); + void onModFilterType(CCObject* pSender); + void changeTabPage(); + + void onSearch(CCObject*); + + static MoreLeaderboards* create(std::string type); + void fadeLoadingCircle(); + void handle_request_mods(std::string const& data); + void handle_request_more(std::string const& data); + void startLoadingLeaderboard(); + + static std::vector getWords(std::string s, std::string delim); + static CCDictionary* responseToDict(const std::string& response); + + void backButton(CCObject*); +}; diff --git a/src/MoreLeaderboards/MoreLeaderboardsCell.cpp b/src/ui/moreleaderboards/mods/MoreLeaderboardsCell.cpp similarity index 50% rename from src/MoreLeaderboards/MoreLeaderboardsCell.cpp rename to src/ui/moreleaderboards/mods/MoreLeaderboardsCell.cpp index 160b659..dd85b84 100644 --- a/src/MoreLeaderboards/MoreLeaderboardsCell.cpp +++ b/src/ui/moreleaderboards/mods/MoreLeaderboardsCell.cpp @@ -1,14 +1,12 @@ -#include "MoreLeaderboardsCell.h" +#include "MoreLeaderboardsCell.hpp" +#include "../MoreLeaderboards.hpp" -void MoreLeaderboardsCell::loadFromDict(cocos2d::CCDictionary* content) -{ - auto winSize = CCDirector::sharedDirector()->getWinSize(); +void MoreLeaderboardsCell::loadFromDict(cocos2d::CCDictionary* content) { auto name = content->valueForKey("modstring")->getCString(); auto mediaMenu = CCMenu::create(); float mediaXPosition = 327; int mediaCount = 0; - std::string usernameTemp = ""; std::vector data = MoreLeaderboards::getWords(name, "?"); @@ -16,68 +14,53 @@ void MoreLeaderboardsCell::loadFromDict(cocos2d::CCDictionary* content) while (data.size() > 0) { std::string id = data[0]; - std::string name = data[1]; + std::string val = data[1]; if (id == "1") { - usernameTemp = name; + usernameTemp = val; } else if (id == "3") { - if (name == "0") { - auto robtopbadge = cocos2d::CCSprite::createWithSpriteFrameName("robtop_badge.png"_spr); - robtopbadge->setPosition({ 30, 20 }); - robtopbadge->setScale(1.225f); - this->m_mainLayer->addChild(robtopbadge); - } else if (name == "2") { - auto elderModBadge = cocos2d::CCSprite::createWithSpriteFrameName("modBadge_01_001.png"); - elderModBadge->setPosition({ 30, 20 }); - elderModBadge->setScale(1.225f); - this->m_mainLayer->addChild(elderModBadge); - } else if (name == "1") { - auto modBadge = cocos2d::CCSprite::createWithSpriteFrameName("modBadge_02_001.png"); - modBadge->setPosition({ 30, 20 }); - modBadge->setScale(1.225f); - this->m_mainLayer->addChild(modBadge); - } else if (name == "3") { - auto modBadge = cocos2d::CCSprite::createWithSpriteFrameName("modBadge_03_001.png"); - modBadge->setPosition({ 30, 20 }); - modBadge->setScale(1.225f); - this->m_mainLayer->addChild(modBadge); + CCSprite* badge = nullptr; + if (val == "0") { + badge = cocos2d::CCSprite::createWithSpriteFrameName("robtop_badge.png"_spr); + } else if (val == "2") { + badge = cocos2d::CCSprite::createWithSpriteFrameName("modBadge_01_001.png"); + } else if (val == "1") { + badge = cocos2d::CCSprite::createWithSpriteFrameName("modBadge_02_001.png"); + } else if (val == "3") { + badge = cocos2d::CCSprite::createWithSpriteFrameName("modBadge_03_001.png"); + } + if (badge) { + badge->setPosition({30, 20}); + badge->setScale(1.225f); + this->m_mainLayer->addChild(badge); } } else if (id == "4") { - if (name != "NULL") { - auto discordSpr = CCSprite::createWithSpriteFrameName("gj_discordIcon_001.png"); + if (val != "NULL") { auto discordBtn = CCMenuItemSpriteExtra::create( - discordSpr, - this, - menu_selector(MoreLeaderboardsCell::callback_link) + CCSprite::createWithSpriteFrameName("gj_discordIcon_001.png"), + this, menu_selector(MoreLeaderboardsCell::callback_link) ); - auto discord_link = CCString::create(name); - discordBtn->setUserObject(discord_link); + discordBtn->setUserObject(CCString::create(val)); mediaMenu->addChild(discordBtn); mediaCount++; } } else if (id == "5") { - if (name != "NULL") { - auto twitchSpr = CCSprite::createWithSpriteFrameName("gj_twitchIcon_001.png"); + if (val != "NULL") { auto twitchBtn = CCMenuItemSpriteExtra::create( - twitchSpr, - this, - menu_selector(MoreLeaderboardsCell::callback_link) + CCSprite::createWithSpriteFrameName("gj_twitchIcon_001.png"), + this, menu_selector(MoreLeaderboardsCell::callback_link) ); - auto twitch_link = CCString::create(name); - twitchBtn->setUserObject(twitch_link); + twitchBtn->setUserObject(CCString::create(val)); mediaMenu->addChild(twitchBtn); mediaCount++; } } else if (id == "6") { - if (name != "NULL") { - auto youtubeSpr = CCSprite::createWithSpriteFrameName("gj_ytIcon_001.png"); + if (val != "NULL") { auto youtubeBtn = CCMenuItemSpriteExtra::create( - youtubeSpr, - this, - menu_selector(MoreLeaderboardsCell::callback_link) + CCSprite::createWithSpriteFrameName("gj_ytIcon_001.png"), + this, menu_selector(MoreLeaderboardsCell::callback_link) ); - auto youtube_link = CCString::create(name); - youtubeBtn->setUserObject(youtube_link); + youtubeBtn->setUserObject(CCString::create(val)); mediaMenu->addChild(youtubeBtn); mediaCount++; } @@ -88,18 +71,16 @@ void MoreLeaderboardsCell::loadFromDict(cocos2d::CCDictionary* content) } auto username = cocos2d::CCLabelBMFont::create(usernameTemp.c_str(), "goldFont.fnt"); - username->setPosition({ 57, 20 }); + username->setPosition({57, 20}); username->setScale(.725f); auto dictData = CCDictionary::create(); dictData->setObject(CCString::create(data2[3]), "accountID"); dictData->setObject(CCString::create(data2[13]), "playerID"); dictData->setObject(CCString::create(usernameTemp.c_str()), "username"); - + auto usernameBtn = CCMenuItemSpriteExtra::create( - username, - this, - menu_selector(MoreLeaderboardsCell::callback_user) + username, this, menu_selector(MoreLeaderboardsCell::callback_user) ); usernameBtn->setPosition({0, 0}); usernameBtn->setAnchorPoint({0, 0.5}); @@ -107,29 +88,24 @@ void MoreLeaderboardsCell::loadFromDict(cocos2d::CCDictionary* content) auto menu = CCMenu::create(); menu->addChild(usernameBtn); - menu->setPosition({ 55, 20 }); - + menu->setPosition({55, 20}); this->m_mainLayer->addChild(menu); - if (mediaCount == 1) { - mediaXPosition = 327; - } else if (mediaCount == 2) { - mediaXPosition = 308; - } else if (mediaCount == 3) { - mediaXPosition = 289; - } + if (mediaCount == 1) mediaXPosition = 327; + else if (mediaCount == 2) mediaXPosition = 308; + else if (mediaCount == 3) mediaXPosition = 289; mediaMenu->alignItemsHorizontallyWithPadding(5); mediaMenu->setAnchorPoint({1, 0.5}); - mediaMenu->setPosition({ mediaXPosition, 20 }); + mediaMenu->setPosition({mediaXPosition, 20}); this->m_mainLayer->addChild(mediaMenu); this->m_mainLayer->setVisible(true); this->m_backgroundLayer->setOpacity(255); -}; +} -MoreLeaderboardsCell::MoreLeaderboardsCell(const char* name, CCSize size) : - GenericListCell(name, size) {} +MoreLeaderboardsCell::MoreLeaderboardsCell(const char* name, CCSize size) + : GenericListCell(name, size) {} MoreLeaderboardsCell* MoreLeaderboardsCell::create(const char* key, CCSize size) { auto ret = new MoreLeaderboardsCell(key, size); @@ -143,16 +119,12 @@ MoreLeaderboardsCell* MoreLeaderboardsCell::create(const char* key, CCSize size) } void MoreLeaderboardsCell::callback_user(CCObject* pSender) { - GameLevelManager* glm = GameLevelManager::sharedState(); - auto data = static_cast(static_cast(pSender)->getUserObject()); auto accountID = numFromString(data->valueForKey("accountID")->getCString()).unwrapOrDefault(); auto playerID = numFromString(data->valueForKey("playerID")->getCString()).unwrapOrDefault(); auto username = data->valueForKey("username")->getCString(); - - glm->storeUserName(playerID, accountID, username); - + GameLevelManager::sharedState()->storeUserName(playerID, accountID, username); ProfilePage::create(accountID, true)->show(); } diff --git a/src/MoreLeaderboards/MoreLeaderboardsCell.h b/src/ui/moreleaderboards/mods/MoreLeaderboardsCell.hpp similarity index 93% rename from src/MoreLeaderboards/MoreLeaderboardsCell.h rename to src/ui/moreleaderboards/mods/MoreLeaderboardsCell.hpp index 7a8a1d0..4498132 100644 --- a/src/MoreLeaderboards/MoreLeaderboardsCell.h +++ b/src/ui/moreleaderboards/mods/MoreLeaderboardsCell.hpp @@ -1,5 +1,5 @@ #pragma once -#include "MoreLeaderboards.h" +#include #include class MoreLeaderboardsCell : public GenericListCell { diff --git a/src/MoreLeaderboards/MoreLeaderboardsListView.cpp b/src/ui/moreleaderboards/mods/MoreLeaderboardsListView.cpp similarity index 61% rename from src/MoreLeaderboards/MoreLeaderboardsListView.cpp rename to src/ui/moreleaderboards/mods/MoreLeaderboardsListView.cpp index 1de6a55..05813db 100644 --- a/src/MoreLeaderboards/MoreLeaderboardsListView.cpp +++ b/src/ui/moreleaderboards/mods/MoreLeaderboardsListView.cpp @@ -1,7 +1,5 @@ -#include "MoreLeaderboardsListView.h" -#include "MoreLeaderboards.h" -#include "MoreLeaderboardsCell.h" -#include "../includes.h" +#include "MoreLeaderboardsListView.hpp" +#include "MoreLeaderboardsCell.hpp" MoreLeaderboardsListView* MoreLeaderboardsListView::create(cocos2d::CCArray* levels, float width, float height) { auto ret = new MoreLeaderboardsListView(); @@ -12,11 +10,10 @@ MoreLeaderboardsListView* MoreLeaderboardsListView::create(cocos2d::CCArray* lev ret = nullptr; } return ret; -}; +} void MoreLeaderboardsListView::setupList(float d) { this->m_itemSeparation = 40.0f; - this->m_tableView->reloadData(); auto coverage = calculateNodeCoverage(m_tableView->m_contentLayer->getChildren()); @@ -27,41 +24,34 @@ void MoreLeaderboardsListView::setupList(float d) { if (this->m_entries->count() == 1) this->m_tableView->moveToTopWithOffset(this->m_itemSeparation); -}; +} -cocos2d::CCRect MoreLeaderboardsListView::calculateNodeCoverage(CCArray* nodes){ +CCRect MoreLeaderboardsListView::calculateNodeCoverage(CCArray* nodes) { CCRect coverage; - CCObject* childObj; - CCARRAY_FOREACH(nodes, childObj) { - if (misc::getNodeName(childObj) != "cocos2d::CCNode" && misc::getNodeName(childObj) != "MoreLeaderboardsCell") continue; - CCNode* child = static_cast(childObj); // android doesnt like dynamic_cast - if(child == nullptr) continue; + for (auto* childObj : CCArrayExt(nodes)) { + CCNode* child = childObj; + if (!child) continue; + // only process MoreLeaderboardsCell entries and plain CCNode spacers + if (!typeinfo_cast(child) && child->getChildrenCount() > 0) continue; + auto contentSize = child->getScaledContentSize(); contentSize.width *= child->getAnchorPoint().x; contentSize.height *= child->getAnchorPoint().y; auto pos = child->getPosition() - contentSize; contentSize = child->getScaledContentSize(); - auto contentPoint = CCPoint { 1.f, 1.f } - child->getAnchorPoint(); + auto contentPoint = CCPoint{1.f, 1.f} - child->getAnchorPoint(); contentSize.width *= contentPoint.x; contentSize.height *= contentPoint.y; auto csize = child->getPosition() + contentSize; - if (pos.x < coverage.origin.x) { - coverage.origin.x = pos.x; - } - if (pos.y < coverage.origin.y) { - coverage.origin.y = pos.y; - } - if (csize.x > coverage.size.width) { - coverage.size.width = csize.x; - } - if (csize.y > coverage.size.height) { - coverage.size.height = csize.y; - } + if (pos.x < coverage.origin.x) coverage.origin.x = pos.x; + if (pos.y < coverage.origin.y) coverage.origin.y = pos.y; + if (csize.x > coverage.size.width) coverage.size.width = csize.x; + if (csize.y > coverage.size.height) coverage.size.height = csize.y; } return coverage; -}; +} void MoreLeaderboardsListView::loadCell(TableViewCell* cell, int index) { static_cast(cell)->loadFromDict( @@ -71,5 +61,5 @@ void MoreLeaderboardsListView::loadCell(TableViewCell* cell, int index) { } TableViewCell* MoreLeaderboardsListView::getListCell(const char* key) { - return new MoreLeaderboardsCell(key, { this->m_width, 40.0f }); -}; + return new MoreLeaderboardsCell(key, {this->m_width, 40.0f}); +} diff --git a/src/ui/moreleaderboards/mods/MoreLeaderboardsListView.hpp b/src/ui/moreleaderboards/mods/MoreLeaderboardsListView.hpp new file mode 100644 index 0000000..9f77127 --- /dev/null +++ b/src/ui/moreleaderboards/mods/MoreLeaderboardsListView.hpp @@ -0,0 +1,12 @@ +#pragma once +#include + +class MoreLeaderboardsListView : public CustomListView { +protected: + void setupList(float) override; + TableViewCell* getListCell(const char* key) override; + void loadCell(TableViewCell* cell, int index) override; + static CCRect calculateNodeCoverage(CCArray* nodes); +public: + static MoreLeaderboardsListView* create(CCArray* levels, float width, float height); +}; diff --git a/src/MoreLeaderboards/SelectRegion.cpp b/src/ui/moreleaderboards/region/SelectRegion.cpp similarity index 68% rename from src/MoreLeaderboards/SelectRegion.cpp rename to src/ui/moreleaderboards/region/SelectRegion.cpp index 8183d85..d273bfc 100644 --- a/src/MoreLeaderboards/SelectRegion.cpp +++ b/src/ui/moreleaderboards/region/SelectRegion.cpp @@ -1,14 +1,13 @@ -#include "SelectRegion.h" +#include "SelectRegion.hpp" -static std::unordered_map RUNNING_REQUESTS {}; std::vector SelectRegion::displayedData = {}; std::vector SelectRegion::getWords(std::string s, std::string delim) { std::vector res; std::string token = ""; - for (int i = 0; i < s.size(); i++) { + for (int i = 0; i < (int)s.size(); i++) { bool flag = true; - for (int j = 0; j < delim.size(); j++) { + for (int j = 0; j < (int)delim.size(); j++) { if (s[i + j] != delim[j]) flag = false; } if (flag) { @@ -25,25 +24,27 @@ std::vector SelectRegion::getWords(std::string s, std::string delim return res; } -void SelectRegion::scene(const std::function& callback) { - auto popup = new SelectRegion(callback); +SelectRegion* SelectRegion::create(const std::function& callback) { + auto ret = new SelectRegion(callback); + if (ret && ret->init()) { + ret->autorelease(); + return ret; + } + CC_SAFE_DELETE(ret); + return nullptr; +} - if (popup && popup->initAnchored(250.0f, 210.0f)) { - popup->autorelease(); +void SelectRegion::scene(const std::function& callback) { + if (auto popup = SelectRegion::create(callback)) { CCDirector::sharedDirector()->getRunningScene()->addChild(popup); - } else { - CC_SAFE_DELETE(popup); } -}; - -bool SelectRegion::setup() { - auto winSize = cocos2d::CCDirector::sharedDirector()->getWinSize(); - auto director = cocos2d::CCDirector::sharedDirector(); +} +bool SelectRegion::init() { + if (!Popup::init(250.0f, 210.0f)) return false; setTouchEnabled(true); setKeypadEnabled(true); - - SelectRegion::loadPage(); + loadPage(); return true; } @@ -58,7 +59,7 @@ void SelectRegion::loadPage() { data->addObject(cell); } - auto border = OldBorder::create(ListView::create(data, 30, 218, 178), { 0xBF, 0x72, 0x3E, 0xFF }, {220, 180}, {1, 1}); + auto border = OldBorder::create(ListView::create(data, 30, 218, 178), {0xBF, 0x72, 0x3E, 0xFF}, {220, 180}, {1, 1}); border->setPosition(m_mainLayer->getContentSize() / 2 - border->getContentSize() / 2); setTouchPriority(100); m_mainLayer->addChild(border); diff --git a/src/ui/moreleaderboards/region/SelectRegion.hpp b/src/ui/moreleaderboards/region/SelectRegion.hpp new file mode 100644 index 0000000..45480f0 --- /dev/null +++ b/src/ui/moreleaderboards/region/SelectRegion.hpp @@ -0,0 +1,25 @@ +#pragma once +#include +#include +#include "SelectRegionCell.hpp" +#include "../../OldBorder.hpp" +#include + +class SelectRegion : public Popup { + LoadingCircle* loading_circle; + std::function selectedRegion; + +protected: + bool init(); + void loadPage(); + + cocos2d::CCSize m_sScrLayerSize; +public: + static std::vector displayedData; + + SelectRegion(const std::function& callback) : selectedRegion(callback) {} + + static SelectRegion* create(const std::function& callback); + static void scene(const std::function& callback); + static std::vector getWords(std::string s, std::string delim); +}; diff --git a/src/MoreLeaderboards/SelectRegionCell.cpp b/src/ui/moreleaderboards/region/SelectRegionCell.cpp similarity index 63% rename from src/MoreLeaderboards/SelectRegionCell.cpp rename to src/ui/moreleaderboards/region/SelectRegionCell.cpp index bf555fc..1612180 100644 --- a/src/MoreLeaderboards/SelectRegionCell.cpp +++ b/src/ui/moreleaderboards/region/SelectRegionCell.cpp @@ -1,4 +1,5 @@ -#include "SelectRegionCell.h" +#include "SelectRegionCell.hpp" +#include "SelectRegion.hpp" std::string SelectRegionCell::country_id = "NAN"; @@ -10,18 +11,17 @@ bool SelectRegionCell::init(std::string mod) { std::string id = data[0]; std::string name = data[1]; - // sprite if (id == "1") { auto username = cocos2d::CCLabelBMFont::create(name.c_str(), "bigFont.fnt"); - username->setPosition({ 38, 21 }); - username->setAnchorPoint({ 0, 0.5 }); + username->setPosition({38, 21}); + username->setAnchorPoint({0, 0.5}); username->limitLabelWidth(100, .550f, .2f); addChild(username); } else if (id == "3") { if (name != "NAN") { std::string spriteName(name); std::transform(spriteName.begin(), spriteName.end(), spriteName.begin(), ::tolower); - if (auto flagSpr = CCSprite::createWithSpriteFrameName((""_spr+spriteName+".png").c_str())) { + if (auto flagSpr = CCSprite::createWithSpriteFrameName((""_spr + spriteName + ".png").c_str())) { flagSpr->setPosition({20, 15}); flagSpr->setScaleY(30 / flagSpr->getContentHeight() * 0.50); flagSpr->setScaleX(std::min(1.0f, 40 / flagSpr->getContentWidth())); @@ -30,15 +30,14 @@ bool SelectRegionCell::init(std::string mod) { } else { auto earthSpr = CCSprite::create("earth_btn.png"_spr); earthSpr->setScale(.425f); - earthSpr->setPosition({ 20, 14 }); + earthSpr->setPosition({20, 14}); addChild(earthSpr); } - id_ctr = name; } else if (id == "5") { auto nbPlayers = cocos2d::CCLabelBMFont::create((name + " players").c_str(), "goldFont.fnt"); - nbPlayers->setPosition({ 38, 8 }); - nbPlayers->setAnchorPoint({ 0, 0.5 }); + nbPlayers->setPosition({38, 8}); + nbPlayers->setAnchorPoint({0, 0.5}); nbPlayers->setScale(.375f); addChild(nbPlayers); } @@ -50,34 +49,22 @@ bool SelectRegionCell::init(std::string mod) { CCMenu* btnMenu = CCMenu::create(); btnMenu->setPosition(0, 0); - if (id_ctr != country_id) { - auto viewSpr = cocos2d::CCSprite::createWithSpriteFrameName("GJ_checkOff_001.png"); - viewSpr->setScale(.575f); - auto viewBtn = CCMenuItemSpriteExtra::create( - viewSpr, - this, - menu_selector(SelectRegionCell::onClick) - ); - viewBtn->setPosition(196, 15); - btnMenu->addChild(viewBtn); - } else { - auto viewSpr = cocos2d::CCSprite::createWithSpriteFrameName("GJ_checkOn_001.png"); - viewSpr->setScale(.575f); - auto viewBtn = CCMenuItemSpriteExtra::create( - viewSpr, - this, - menu_selector(SelectRegionCell::onClick) - ); - viewBtn->setPosition(196, 15); - btnMenu->addChild(viewBtn); - } - + const char* checkFrame = (id_ctr != country_id) + ? "GJ_checkOff_001.png" + : "GJ_checkOn_001.png"; + auto viewSpr = cocos2d::CCSprite::createWithSpriteFrameName(checkFrame); + viewSpr->setScale(.575f); + auto viewBtn = CCMenuItemSpriteExtra::create( + viewSpr, this, menu_selector(SelectRegionCell::onClick) + ); + viewBtn->setPosition(196, 15); + btnMenu->addChild(viewBtn); addChild(btnMenu); return true; -}; +} -void SelectRegionCell::onClick(cocos2d::CCObject* pSender) { +void SelectRegionCell::onClick(cocos2d::CCObject*) { selectedRegion(country_id = id_ctr); } diff --git a/src/MoreLeaderboards/SelectRegionCell.h b/src/ui/moreleaderboards/region/SelectRegionCell.hpp similarity index 86% rename from src/MoreLeaderboards/SelectRegionCell.h rename to src/ui/moreleaderboards/region/SelectRegionCell.hpp index e1bec07..e5a9f9b 100644 --- a/src/MoreLeaderboards/SelectRegionCell.h +++ b/src/ui/moreleaderboards/region/SelectRegionCell.hpp @@ -1,6 +1,8 @@ #pragma once -#include "SelectRegion.h" -#include +#include +#include + +class SelectRegion; class SelectRegionCell : public cocos2d::CCLayer { std::function selectedRegion; @@ -13,4 +15,4 @@ class SelectRegionCell : public cocos2d::CCLayer { static std::string country_id; bool init(std::string mod); static SelectRegionCell* create(std::string mod, const std::function& callback); -}; \ No newline at end of file +}; diff --git a/src/MoreLeaderboards/Newtab.cpp b/src/ui/moreleaderboards/tabs/TabButton.cpp similarity index 89% rename from src/MoreLeaderboards/Newtab.cpp rename to src/ui/moreleaderboards/tabs/TabButton.cpp index 2a4b0db..e897345 100644 --- a/src/MoreLeaderboards/Newtab.cpp +++ b/src/ui/moreleaderboards/tabs/TabButton.cpp @@ -1,8 +1,8 @@ -#include "Newtab.h" +#include "TabButton.hpp" NewTabButton* NewTabButton::create( - TabBaseColor unselected, TabBaseColor selected, CCNode* icon, cocos2d::CCObject* target, - cocos2d::SEL_MenuHandler callback + TabBaseColor unselected, TabBaseColor selected, CCNode* icon, + cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback ) { auto ret = new NewTabButton(); auto sprOff = NewTabButtonSprite::create(icon, unselected); @@ -25,10 +25,9 @@ CCSize NewBasedButtonSprite::getMaxTopSize() const { void NewBasedButtonSprite::setTopOffset(CCPoint const& offset) { m_topOffset = offset; - if (m_onTop) { - m_onTop->setPosition(this->getContentSize() / 2 + offset); - } + if (m_onTop) m_onTop->setPosition(this->getContentSize() / 2 + offset); } + void NewBasedButtonSprite::setTopRelativeScale(float scale) { m_onTopRelativeScale = scale; if (m_onTop) { @@ -63,10 +62,7 @@ NewBasedButtonSprite::~NewBasedButtonSprite() {} NewTabButtonSprite* NewTabButtonSprite::create(CCNode* icon, TabBaseColor color, TabBaseSize size) { auto ret = new NewTabButtonSprite(); - if (ret && ret->init( - icon, BaseType::Tab, - static_cast(size), static_cast(color) - )) { + if (ret && ret->init(icon, BaseType::Tab, static_cast(size), static_cast(color))) { ret->autorelease(); return ret; } @@ -75,10 +71,10 @@ NewTabButtonSprite* NewTabButtonSprite::create(CCNode* icon, TabBaseColor color, } static std::string baseEnumsToString(BaseType type, int size, int color) { -#define ENUMS_TO_STRING(ty_) \ - case BaseType::ty_: { \ - sizeStr = baseEnumToString(static_cast(size));\ - colorStr = baseEnumToString(static_cast(color));\ +#define ENUMS_TO_STRING(ty_) \ + case BaseType::ty_: { \ + sizeStr = baseEnumToString(static_cast(size)); \ + colorStr = baseEnumToString(static_cast(color)); \ } break const char* typeStr = baseEnumToString(type); @@ -115,4 +111,4 @@ bool NewBasedButtonSprite::init(CCNode* ontop, BaseType type, int size, int colo } return true; -} \ No newline at end of file +} diff --git a/src/ui/moreleaderboards/tabs/TabButton.hpp b/src/ui/moreleaderboards/tabs/TabButton.hpp new file mode 100644 index 0000000..5a5ad11 --- /dev/null +++ b/src/ui/moreleaderboards/tabs/TabButton.hpp @@ -0,0 +1,43 @@ +#pragma once +#include + +class NewTabButton : public CCMenuItemToggler { +public: + static NewTabButton* create( + TabBaseColor unselected, TabBaseColor selected, CCNode* icon, + cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback + ); +}; + +class NewBasedButtonSprite : public cocos2d::CCSprite { +protected: + BaseType m_type; + int m_size; + int m_color; + cocos2d::CCNode* m_onTop = nullptr; + float m_onTopRelativeScale = 1.3f; + cocos2d::CCPoint m_topOffset = cocos2d::CCPointZero; + + bool init(cocos2d::CCNode* ontop, BaseType type, int size, int color); + bool initWithSprite(const char* sprName, float sprScale, BaseType type, int size, int color); + bool initWithSpriteFrameName(const char* sprName, float sprScale, BaseType type, int size, int color); + + virtual cocos2d::CCSize getMaxTopSize() const; + virtual ~NewBasedButtonSprite(); + +public: + static NewBasedButtonSprite* create(cocos2d::CCNode* ontop, BaseType type, int size, int color); + + void setTopOffset(cocos2d::CCPoint const& offset); + void setTopRelativeScale(float scale); + cocos2d::CCNode* getTopNode() const; +}; + +class NewTabButtonSprite : public NewBasedButtonSprite { +public: + static NewTabButtonSprite* create( + CCNode* icon, + TabBaseColor color, + TabBaseSize size = TabBaseSize::Normal + ); +}; diff --git a/test/mod.json b/test/mod.json index 2f1f80d..2bf5819 100644 --- a/test/mod.json +++ b/test/mod.json @@ -1,21 +1,17 @@ { - "geode": "4.9.0", + "geode": "5.8.2", "gd": { - "win": "2.2074", - "android": "2.2074", - "mac": "2.2074", - "ios": "2.2074" + "win": "2.2081", + "android": "2.2081", + "mac": "2.2081", + "ios": "2.2081" }, "id": "gdutilsdevs.test", "name": "GDUtils Test Mod", "version": "v1.0.0", "developer": "Firee", "description": "", - "dependencies": [ - { - "id": "gdutilsdevs.gdutils", - "version": ">=v1.4.0-beta.6", - "importance": "required" - } - ] + "dependencies": { + "gdutilsdevs.gdutils": ">=v1.6.0" + } } diff --git a/test/src/main.cpp b/test/src/main.cpp index 3509891..c4e7b2e 100644 --- a/test/src/main.cpp +++ b/test/src/main.cpp @@ -26,8 +26,22 @@ class $modify(MenuLayer) { }; $execute { - new EventListener>(+[](GDUtils::Events::OnRate* e) { - log::info("A rate event with the title {}", e->getTitle()); + GDUtils::Events::OnRate().listen([](EventData const& e) { + log::info("A rate event with the title {}", e.getTitle()); + return ListenerResult::Propagate; + }); + + GDUtils::Events::OnRate(EventType::Daily).listen([](EventData const& e) { + log::info("A daily event with the level name {}", e.getLevelName()); + return ListenerResult::Propagate; + }); + + GDUtils::Events::OnServerConnect().listen([](bool const& connected) { + Loader::get()->queueInMainThread([connected]() { + if (connected) { + log::info("I am connected to the notification servers!"); + } + }); return ListenerResult::Propagate; }); }