diff --git a/ABOUT.md b/ABOUT.md new file mode 100644 index 0000000..d73fefe --- /dev/null +++ b/ABOUT.md @@ -0,0 +1,23 @@ +# GD-Roulette + +A Geometry Dash Level Roulette. + +## Features + +- Normal List (regular levels ranging from Easy to Extreme Demon) +- Demon List +- Challenge List +- Skip levels you can't beat +- Auto pause after reaching the goal percentage (can be disabled) + +## How To Play + +Simply choose the list you want to play levels from (the default is normal list), select a difficulty, and press Start! +A random level of the chosen difficulty will be given to you and you will need to achieve a certain percentage in said level (starts from 1%, and increments by 1 after each level beaten). +Normally, you're supposed to get to get the goal percentage, and not higher. Unfortunately, some levels don't have a way to die at said percentage, so the goal will automatically be your death percentage + 1. + +After reaching/surpassing the goal percentage in a round of roulette, the game will automatically pause after you die. This can be disabled in the mod's Geode settings. + +If a level is too hard, you can click on the Skip button, which will subtract 1 skip from your skips. You can set the number of skips you are allowed to use during a round of roulette in the roulette's settings (accessible from the info icon in the roulette while not playing it, or from the Geode mod settings). + +And that's pretty much it! Have fun rouletting! diff --git a/CHANGELOG.md b/CHANGELOG.md index d8ec954..b706ca7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [1.6.1-beta.1] - 2024-02-07 + +### Added + +- Auto pause option +- Some IDs to layers that are modified + +### Changed + +- Target Geode 2.0.0-beta.16 +- Some `static_cast`s to `as` +- CHANGELOG.md layout to "Added", "Changed" then "Fixed" +- Target any Node-IDs version that matches or is greater than 1.3.0 +- Changed some for loops to getChildByID +- Renamed RouletteManager::lastLevelID to currentLevelID +- Renamed RouletteManager::lastLevelPercentage to currentLevelPercentage +- Removed Node-IDs dependency in CMakeLists.txt +- Removed RouletteManager::levelCreatorName +- Renamed about.md to ABOUT.md + +### Fixed + +- Goal percentage appearing in a level that isn't the current roulette level + ## [1.6.0-beta.4] - 2024-02-06 ### Fixed @@ -13,7 +37,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [1.6.0-beta.3] - 2024-02-04 -### Added +### Changed - Geode 2.0.0-beta.15 support diff --git a/CMakeLists.txt b/CMakeLists.txt index cf201d5..3b3a864 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ endif() add_subdirectory($ENV{GEODE_SDK} ${CMAKE_CURRENT_BINARY_DIR}/geode) -setup_geode_mod(${PROJECT_NAME} EXTERNALS geode.node-ids:1.1.4) +setup_geode_mod(${PROJECT_NAME}) # Warnings as errors set_property(TARGET ${PROJECT_NAME} PROPERTY COMPILE_WARNING_AS_ERROR ON) diff --git a/mod.json b/mod.json index 8501ae8..18177dd 100644 --- a/mod.json +++ b/mod.json @@ -1,10 +1,10 @@ { - "geode": "2.0.0-beta.15", + "geode": "2.0.0-beta.16", "gd": { "win": "2.204", "android": "2.205" }, - "version": "v1.6.0-beta.4", + "version": "v1.6.1-beta.1", "id": "spaghettdev.gd-roulette", "name": "GD-Roulette", "developer": "SpaghettDev", @@ -22,7 +22,7 @@ "dependencies": [ { "id": "geode.node-ids", - "version": "v1.1.4", + "version": ">=v1.1.4", "importance": "required" } ], @@ -44,6 +44,12 @@ "default": 3, "max": 9999, "min": 0 + }, + "auto-pause": { + "name": "Auto Pause", + "description": "Enable or disable auto pausing after getting the goal percentage during a round of roulette.", + "type": "bool", + "default": true } } } \ No newline at end of file diff --git a/src/custom_layers/ConfirmationLayer.cpp b/src/custom_layers/ConfirmationLayer.cpp index ff1b1e0..09f682c 100644 --- a/src/custom_layers/ConfirmationLayer.cpp +++ b/src/custom_layers/ConfirmationLayer.cpp @@ -26,7 +26,7 @@ bool ConfirmationAlertLayer::init() auto winSize = CCDirector::sharedDirector()->getWinSize(); - auto bg = static_cast( + auto bg = as( m_mainLayer->getChildren()->objectAtIndex(0) ); auto bgContentSize = bg->getContentSize(); diff --git a/src/custom_layers/IntegerInputLayer.cpp b/src/custom_layers/IntegerInputLayer.cpp index 9955fa6..60d49e9 100644 --- a/src/custom_layers/IntegerInputLayer.cpp +++ b/src/custom_layers/IntegerInputLayer.cpp @@ -92,7 +92,7 @@ void IntegerInputLayer::onClose(CCObject*) try { m_integer = std::stoi( - static_cast(m_buttonMenu->getChildByTag(1))->getString() + as(m_buttonMenu->getChildByTag(1))->getString() ); } @@ -115,7 +115,7 @@ void IntegerInputLayer::keyDown(enumKeyCodes key) void IntegerInputLayer::onLeftButton(CCObject*) { - const auto inputNode = static_cast(m_buttonMenu->getChildByTag(1)); + const auto inputNode = as(m_buttonMenu->getChildByTag(1)); try { @@ -135,7 +135,7 @@ void IntegerInputLayer::onLeftButton(CCObject*) void IntegerInputLayer::onRightButton(CCObject*) { - const auto inputNode = static_cast(m_buttonMenu->getChildByTag(1)); + const auto inputNode = as(m_buttonMenu->getChildByTag(1)); try { diff --git a/src/layers/CreatorLayer.cpp b/src/layers/CreatorLayer.cpp index f98d393..b1d8f4c 100644 --- a/src/layers/CreatorLayer.cpp +++ b/src/layers/CreatorLayer.cpp @@ -37,6 +37,7 @@ class $modify(RouletteButton, CreatorLayer) rouletteSprite->setPosition({ 22.25f, 23.75f }); rouletteButton->addChild(rouletteSprite); rouletteButton->setPosition({ 25.f, 160.f }); + rouletteButton->setID("roulette-button"_spr); menu->addChild(rouletteButton); diff --git a/src/layers/LevelInfoLayer.cpp b/src/layers/LevelInfoLayer.cpp index 007c885..1e23db9 100644 --- a/src/layers/LevelInfoLayer.cpp +++ b/src/layers/LevelInfoLayer.cpp @@ -1,3 +1,5 @@ +#include + #include "../roulette/manager/RouletteManager.hpp" #include "../roulette/layers/RouletteLayer.hpp" @@ -6,15 +8,20 @@ using namespace geode::prelude; +// not a field because the field dtor crashes the game idk why +std::list levelIDs{}; + class $modify(LevelInfoLayer) { bool init(GJGameLevel* level, bool p1) { if (!LevelInfoLayer::init(level, p1)) return false; - if (g_rouletteManager.isPlayingRoulette) + if (g_rouletteManager.isPlayingRoulette && level->m_levelID.value() == g_rouletteManager.currentLevelID) { - CCLabelBMFont* normalPercentageLabel = static_cast(this->getChildByID("normal-mode-percentage")); + levelIDs.push_back(level->m_levelID); + + CCLabelBMFont* normalPercentageLabel = as(this->getChildByID("normal-mode-percentage")); float goalOffset = .0f; // wtf v2 @@ -25,16 +32,15 @@ class $modify(LevelInfoLayer) else goalOffset = 39.f; - if (normalPercentageLabel == nullptr) return true; - auto goalPercentage = CCLabelBMFont::create( - fmt::format("({}%)", static_cast(g_rouletteManager.levelPercentageGoal)).c_str(), + fmt::format("({}%)", g_rouletteManager.levelPercentageGoal).c_str(), "bigFont.fnt" ); goalPercentage->setPosition({ normalPercentageLabel->getPositionX() + goalOffset, normalPercentageLabel->getPositionY() }); goalPercentage->setScale(.4f); goalPercentage->setColor({ 125, 125, 125 }); goalPercentage->setZOrder(3); + goalPercentage->setID("goal-progress-label"_spr); this->addChild(goalPercentage); } @@ -43,13 +49,19 @@ class $modify(LevelInfoLayer) void onBack(CCObject* sender) { - if (g_rouletteManager.rouletteLayer) + if (levelIDs.size() != 1) + levelIDs.pop_back(); + + if (g_rouletteManager.isPlayingRoulette && g_rouletteManager.rouletteLayer && levelIDs.back() == g_rouletteManager.currentLevelID) { - static_cast( + as( g_rouletteManager.rouletteLayer->m_pPlayingMenu->getChildByTag(20) )->setString(fmt::format("{}%", g_rouletteManager.levelPercentageGoal).c_str()); } + if (levelIDs.size() == 1) + levelIDs.pop_back(); + LevelInfoLayer::onBack(sender); } }; diff --git a/src/layers/PauseLayer.cpp b/src/layers/PauseLayer.cpp index a2202ab..b9503e1 100644 --- a/src/layers/PauseLayer.cpp +++ b/src/layers/PauseLayer.cpp @@ -13,42 +13,26 @@ class $modify(PauseLayer) { PauseLayer::customSetup(); - if (g_rouletteManager.isPlayingRoulette) - { - const PlayLayer* playLayer = GameManager::sharedState()->getPlayLayer(); + const PlayLayer* playLayer = GameManager::sharedState()->getPlayLayer(); - CCNode* normalPercentageLabel = nullptr; + if (g_rouletteManager.isPlayingRoulette && playLayer->m_level->m_levelID.value() == g_rouletteManager.currentLevelID) + { + CCLabelBMFont* normalPercentageLabel = as(this->getChildByID("normal-progress-label")); float goalOffset = 24.f; if (playLayer->m_level->m_normalPercent < 10) goalOffset = 28.f; else if (playLayer->m_level->m_normalPercent <= 100) goalOffset = 40.f; - - // normal mode percentage is always first in the array - CCObject* pauseLayerObject; - CCARRAY_FOREACH(this->getChildren(), pauseLayerObject) - { - if ( - auto levelInfoLayerLabel = typeinfo_cast(pauseLayerObject); - levelInfoLayerLabel && - fmt::format("{}%", playLayer->m_level->m_normalPercent.value()) == levelInfoLayerLabel->getString() - ) { - normalPercentageLabel = levelInfoLayerLabel; - break; - } - }; - - if (normalPercentageLabel == nullptr) return; - auto goalPercentage = CCLabelBMFont::create( - fmt::format("({}%)", static_cast(g_rouletteManager.levelPercentageGoal)).c_str(), + fmt::format("({}%)", g_rouletteManager.levelPercentageGoal).c_str(), "bigFont.fnt" ); goalPercentage->setPosition({ normalPercentageLabel->getPositionX() + goalOffset, normalPercentageLabel->getPositionY() }); goalPercentage->setScale(.5f); goalPercentage->setColor({ 125, 125, 125 }); goalPercentage->setZOrder(4); + goalPercentage->setID("goal-progress-label"_spr); this->addChild(goalPercentage); } } diff --git a/src/layers/PlayLayer.cpp b/src/layers/PlayLayer.cpp index e00a31d..0ba6107 100644 --- a/src/layers/PlayLayer.cpp +++ b/src/layers/PlayLayer.cpp @@ -53,23 +53,27 @@ class $modify(PlayLayerPause, PlayLayer) if ( const int percentage = this->getCurrentPercentInt(); g_rouletteManager.isPlayingRoulette && - this->m_level->m_levelID == g_rouletteManager.lastLevelID && + this->m_level->m_levelID == g_rouletteManager.currentLevelID && !this->m_isPracticeMode && percentage >= g_rouletteManager.levelPercentageGoal ) { if (delta > .2f/* && !this->m_player1->m_isDead*/) { g_rouletteManager.hasFinishedPreviousLevel = true; - g_rouletteManager.lastLevelPercentage = percentage; + g_rouletteManager.currentLevelPercentage = percentage; g_rouletteManager.levelPercentageGoal = percentage + 1; g_rouletteManager.numLevels++; - const auto runningScene = CCDirector::sharedDirector()->getRunningScene(); - m_fields->pauseGameAction = runningScene->runAction( - CCSequence::create( - CCDelayTime::create(1.f), CCCallFunc::create(runningScene, callfunc_selector(PlayLayerPause::pause)), nullptr - ) - ); + if (Mod::get()->getSettingValue("auto-pause")) + { + const auto runningScene = CCDirector::sharedDirector()->getRunningScene(); + + m_fields->pauseGameAction = runningScene->runAction( + CCSequence::create( + CCDelayTime::create(1.f), CCCallFunc::create(runningScene, callfunc_selector(PlayLayerPause::pause)), nullptr + ) + ); + } } } @@ -81,11 +85,11 @@ class $modify(PlayLayerPause, PlayLayer) { if ( g_rouletteManager.isPlayingRoulette && - this->m_level->m_levelID == g_rouletteManager.lastLevelID && + this->m_level->m_levelID == g_rouletteManager.currentLevelID && !this->m_isPracticeMode ) { g_rouletteManager.hasFinishedPreviousLevel = true; - g_rouletteManager.lastLevelPercentage = 100; + g_rouletteManager.currentLevelPercentage = 100; g_rouletteManager.levelPercentageGoal = 100; g_rouletteManager.numLevels++; } diff --git a/src/roulette/layers/RouletteInfoLayer.cpp b/src/roulette/layers/RouletteInfoLayer.cpp index 53b0df0..2e43416 100644 --- a/src/roulette/layers/RouletteInfoLayer.cpp +++ b/src/roulette/layers/RouletteInfoLayer.cpp @@ -89,7 +89,7 @@ void RouletteInfoLayer::destroyLayerChildren() { for (unsigned int i = 0; i < this->getChildrenCount(); i++) { - auto node = static_cast(this->getChildren()->objectAtIndex(0)); + auto node = as(this->getChildren()->objectAtIndex(0)); node->removeFromParentAndCleanup(true); } @@ -106,8 +106,8 @@ void RouletteInfoLayer::onToggleButton(CCObject* sender) { sender->retain(); - auto button = static_cast(sender); - auto parent = static_cast(button->getParent()); + auto button = as(sender); + auto parent = as(button->getParent()); auto ind = roulette::utils::getIndexOf(g_rouletteManager.getFromSaveContainer("selected-list-array").as_array(), true); g_rouletteManager.getFromSaveContainer("selected-list-array").as_array().at(ind) = false; @@ -117,10 +117,10 @@ void RouletteInfoLayer::onToggleButton(CCObject* sender) switch (button->getTag()) { case 0: - static_cast( + as( g_rouletteManager.rouletteLayer->m_pMainMenu->getChildByTag(4) )->setColor({ 125, 125, 125 }); - static_cast( + as( g_rouletteManager.rouletteLayer->m_pMainMenu->getChildByTag(5) )->setColor({ 125, 125, 125 }); @@ -130,25 +130,25 @@ void RouletteInfoLayer::onToggleButton(CCObject* sender) break; case 1: - static_cast( + as( g_rouletteManager.rouletteLayer->m_pMainMenu->getChildByTag(g_rouletteManager.previousDifficulty) )->setColor({ 125, 125, 125 }); - static_cast( + as( g_rouletteManager.rouletteLayer->m_pMainMenu->getChildByTag(4) )->setColor({ 125, 125, 125 }); - static_cast( + as( g_rouletteManager.rouletteLayer->m_pMainMenu->getChildByTag(5) )->setColor({ 255, 255, 255 }); break; case 2: - static_cast( + as( g_rouletteManager.rouletteLayer->m_pMainMenu->getChildByTag(g_rouletteManager.previousDifficulty) )->setColor({ 125, 125, 125 }); - static_cast( + as( g_rouletteManager.rouletteLayer->m_pMainMenu->getChildByTag(4) )->setColor({ 255, 255, 255 }); - static_cast( + as( g_rouletteManager.rouletteLayer->m_pMainMenu->getChildByTag(5) )->setColor({ 125, 125, 125 }); break; @@ -162,7 +162,7 @@ void RouletteInfoLayer::onNumSkipsButton(CCObject*) { m_integer_input_layer->setup({ "Number Of Skips", "Skips", - 0, 3, 9999, static_cast(Mod::get()->getSettingValue("max-skips")), + 0, 3, 9999, as(Mod::get()->getSettingValue("max-skips")), [&](auto iil) { Mod::get()->setSettingValue("max-skips", iil->m_integer); } diff --git a/src/roulette/layers/RouletteLayer.cpp b/src/roulette/layers/RouletteLayer.cpp index 625b982..ed6b4c8 100644 --- a/src/roulette/layers/RouletteLayer.cpp +++ b/src/roulette/layers/RouletteLayer.cpp @@ -356,10 +356,12 @@ bool RouletteLayer::init() } for (int i = 6; i < 11; i++) + { if (g_rouletteManager.getArrayState(g_rouletteManager.getFromSaveContainer("demon-difficulty-array"), i - 6)) - static_cast( + as( m_pMainMenu->getChildByTag(i) )->setColor({ 255, 255, 255 }); + } } @@ -429,15 +431,13 @@ void RouletteLayer::onDifficultyChosen(CCObject* sender) return; auto tag = sender->getTag(); - auto difficultyButton = static_cast(sender); + auto difficultyButton = as(sender); // check if difficultyButton is one of the demon types and not a regular difficulty if (tag > 5 && (tag < 10 || tag > 5)) { int ind = roulette::utils::getIndexOf(g_rouletteManager.getFromSaveContainer("demon-difficulty-array").as_array(), true); - static_cast( - m_pMainMenu->getChildByTag(ind + 6) - )->setColor({ 125, 125, 125 }); + as(m_pMainMenu->getChildByTag(ind + 6))->setColor({ 125, 125, 125 }); g_rouletteManager.getFromSaveContainer("demon-difficulty-array").as_array().at(ind) = false; g_rouletteManager.getFromSaveContainer("demon-difficulty-array").as_array().at(tag - 6) = true; @@ -448,9 +448,7 @@ void RouletteLayer::onDifficultyChosen(CCObject* sender) onPlusButton(nullptr); int ind = roulette::utils::getIndexOf(g_rouletteManager.getFromSaveContainer("difficulty-array").as_array(), true); - static_cast( - m_pMainMenu->getChildByTag(ind) - )->setColor({ 125, 125, 125 }); + as(m_pMainMenu->getChildByTag(ind))->setColor({ 125, 125, 125 }); g_rouletteManager.getFromSaveContainer("difficulty-array").as_array().at(ind) = false; g_rouletteManager.getFromSaveContainer("difficulty-array").as_array().at(tag) = true; @@ -505,7 +503,7 @@ void RouletteLayer::onPlusButton(CCObject*) void RouletteLayer::onLevelInfo(CCObject* sender) { - auto textButton = static_cast(sender); + auto textButton = as(sender); std::string text; switch (textButton->getTag()) @@ -562,27 +560,27 @@ void RouletteLayer::onNextButton(CCObject*) if (m_list_fetcher.isFetching) return; - if (g_rouletteManager.lastLevelPercentage == 100) + if (g_rouletteManager.currentLevelPercentage == 100) { onNextLevel(false, false); - static_cast(m_pFinishedMenu->getChildByTag(2))->setString( + as(m_pFinishedMenu->getChildByTag(2))->setString( fmt::format("Skips Used: {}", g_rouletteManager.skipsUsed).c_str() ); - static_cast(m_pFinishedMenu->getChildByTag(3))->setString( + as(m_pFinishedMenu->getChildByTag(3))->setString( fmt::format("Levels Played: {}", g_rouletteManager.numLevels).c_str() ); m_pPlayingMenu->setVisible(false); m_pFinishedMenu->setVisible(true); } - else if (g_rouletteManager.lastLevelPercentage != 0 && g_rouletteManager.hasFinishedPreviousLevel) + else if (g_rouletteManager.currentLevelPercentage != 0 && g_rouletteManager.hasFinishedPreviousLevel) { g_rouletteManager.hasFinishedPreviousLevel = false; onNextLevel(false, true, -125.f); - static_cast( + as( m_pPlayingMenu->getChildByTag(20) )->setString(fmt::format("{}%", g_rouletteManager.levelPercentageGoal).c_str()); @@ -600,9 +598,7 @@ void RouletteLayer::onNextButton(CCObject*) // ), 1.2f, .8f, 1, "bigFont.fnt" // )); Notification::create( - fmt::format( - "You need to get at least {}%!", static_cast(g_rouletteManager.levelPercentageGoal) - ), + fmt::format("You need to get at least {}%!", g_rouletteManager.levelPercentageGoal), NotificationIcon::Error )->show(); } @@ -629,7 +625,7 @@ void RouletteLayer::onResetButton(CCObject*) m_pFinishedMenu->setVisible(false); m_pErrorMenu->setVisible(false); - static_cast(m_pPlayingMenu->getChildByTag(20))->setString( + as(m_pPlayingMenu->getChildByTag(20))->setString( fmt::format("{}%", g_rouletteManager.levelPercentageGoal).c_str() ); @@ -651,7 +647,7 @@ void RouletteLayer::onSkipButton(CCObject*) if (m_list_fetcher.isFetching) return; - if (g_rouletteManager.lastLevelPercentage == 100) + if (g_rouletteManager.currentLevelPercentage == 100) { onNextButton(nullptr); return; @@ -694,9 +690,7 @@ void RouletteLayer::finishLevelRoulette() if (m_level.is_null()) { - static_cast( - m_pErrorMenu->getChildByTag(2) - )->setString(m_list_fetcher_error.c_str()); + as(m_pErrorMenu->getChildByTag(2))->setString(m_list_fetcher_error.c_str()); m_pPlayingMenu->setVisible(false); m_pErrorMenu->setVisible(true); @@ -706,16 +700,15 @@ void RouletteLayer::finishLevelRoulette() onNextLevel(true); - g_rouletteManager.lastLevelID = std::stoi(m_level.get("id")); - g_rouletteManager.levelCreatorName = m_level.get("author"); + g_rouletteManager.currentLevelID = std::stoi(m_level.get("id")); - static_cast( + as( m_pPlayingMenu->getChildByTag(1)->getChildren()->objectAtIndex(0) )->setString(m_level.get("name").c_str()); - static_cast( + as( m_pPlayingMenu->getChildByTag(2)->getChildren()->objectAtIndex(0) )->setString(("by " + m_level.get("author")).c_str()); - static_cast( + as( m_pPlayingMenu->getChildByTag(3)->getChildren()->objectAtIndex(0) )->setString(("ID: " + m_level.get("id")).c_str()); diff --git a/src/roulette/manager/RouletteManager.hpp b/src/roulette/manager/RouletteManager.hpp index e456ced..4bf5808 100644 --- a/src/roulette/manager/RouletteManager.hpp +++ b/src/roulette/manager/RouletteManager.hpp @@ -35,10 +35,9 @@ struct RouletteManager // inline static matjson::Value* demonDifficultyArr; // 5 // inline static matjson::Value* selectedListArr; // 3 - inline static int lastLevelID = 0; - inline static int lastLevelPercentage = 0; + inline static int currentLevelID = 0; + inline static int currentLevelPercentage = 0; inline static int levelPercentageGoal = 1; - inline static std::string levelCreatorName = ""; inline static int skipsUsed = 0; @@ -80,6 +79,7 @@ struct RouletteManager } } + // not using getSavedValue because i want a reference and not a copy matjson::Value& getFromSaveContainer(std::string_view const key) { return Mod::get()->getSaveContainer().as_object()[key]; @@ -94,10 +94,9 @@ struct RouletteManager { isPlayingRoulette = false; hasFinishedPreviousLevel = false; - lastLevelID = 0; - lastLevelPercentage = 0; + currentLevelID = 0; + currentLevelPercentage = 0; levelPercentageGoal = 1; - levelCreatorName = ""; skipsUsed = 0; numLevels = 0; }