diff --git a/README.md b/README.md index e8a784a..8801f71 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ -# GoldUserCoins +# Gold User Coins -Geode mod that causes all in-game user coins to be rendered as gold secret coins. 100% cosmetic \ No newline at end of file +Geode mod that causes all in-game user coins to be rendered as gold secret coins. + +This is a purely visual change. \ No newline at end of file diff --git a/changelog.md b/changelog.md index 554b252..6130209 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ +# 2.0.0 +- No longer done via patching the game, should be easy to update now :D (thank you spaghettdev) +- Coins in the level complete UI are also gold now +- Compatability with Coins in Pause Menu mod +- Added settings + # 1.0.2 - Fixed reloading resources (e.g. from graphics settings) undoing the texture swap # 1.0.0 -- Initial release \ No newline at end of file +- Initial releasedo \ No newline at end of file diff --git a/mod.json b/mod.json index 03565ee..77893cd 100644 --- a/mod.json +++ b/mod.json @@ -1,12 +1,45 @@ { - "geode": "3.4.0", + "geode": "4.0.1", "gd": { - "win": "2.206" + "win": "2.2074", + "android": "2.2074" }, - "version": "v1.0.3", + "version": "v2.0.0", "id": "colon.gold_user_coins", "name": "Gold User Coins", "developer": "Colon", "description": "Causes user coins to render as secret coins", - "repository": "https://github.com/GDColon/Gold-User-Coins" + "links": { + "source": "https://github.com/GDColon/Gold-User-Coins" + }, + "settings": { + "goldUI": { + "name": "Gold coins on end screen", + "description": "If gold coins should also be shown on the level's end screen\n\n(the particle effect during the animation is still the wrong color, send me some delicious grilled squid and I might get around to fixing it)", + "type": "bool", + "default": true, + "requires-restart": true + }, + + "noBronze": { + "name": "Remove bronze coin tint", + "description": "Removes the bronze coloring for unverified user coins", + "type": "bool", + "default": true + }, + + "goldCoinsEditor": { + "name": "Sneaky sneaky", + "description": "Hold ALT while placing a user coin in the editor to place a real gold one instead (will not save)", + "type": "bool", + "default": false + } + }, + "dependencies": [ + { + "id": "geode.node-ids", + "version": ">=1.16.0", + "importance": "required" + } + ] } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 2ab63c9..a3430db 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,11 +2,25 @@ #include #include #include +#include +#include +#include +#include +#include using namespace geode::prelude; bool swappedTextures = false; +const int GOLD_COIN = 142; +const int USER_COIN = 1329; +const ccColor3B BRONZE_COLOR = ccColor3B{255, 175, 75}; +void removeUITint(CCLayer* layer, std::string name) { + auto spr = layer->getChildByID(name); + if (spr) static_cast(spr)->setColor(ccWHITE); +} + +// swap coin textures class $modify(MenuLayer) { bool init() { if (!MenuLayer::init()) return false; @@ -21,42 +35,114 @@ class $modify(MenuLayer) { swapTexture("secretCoin_01" + suffix, "secretCoin_2_01" + suffix); swapTexture("secretCoin_b_01" + suffix, "secretCoin_2_b_01" + suffix); } + if (Mod::get()->getSettingValue("goldUI")) swapTexture("secretCoinUI_001.png", "secretCoinUI2_001.png"); return true; } - void swapTexture(std::string oldKey, std::string newKey) { + void swapTexture(std::string goldKey, std::string userKey) { auto textureCache = CCSpriteFrameCache::get(); - auto goldTexture = textureCache->spriteFrameByName(oldKey.c_str()); - textureCache->removeSpriteFrameByName(newKey.c_str()); - textureCache->addSpriteFrame(goldTexture, newKey.c_str()); + auto goldTexture = textureCache->spriteFrameByName(goldKey.c_str()); + textureCache->removeSpriteFrameByName(userKey.c_str()); + textureCache->addSpriteFrame(goldTexture, userKey.c_str()); + } +}; + +// unset swapped flag if reloading textures +class $modify(LoadingLayer) { + bool init(bool p0) { + swappedTextures = false; + return LoadingLayer::init(p0); } }; +// detect and remove the bronze tint on unverified coins class $modify(CCSprite) { - // removes the bronze tint on unverified coins void setColor(cocos2d::ccColor3B const& col) { - GameObject* gameObj = typeinfo_cast(this); - if (gameObj && gameObj->m_objectID == 1329) CCSprite::setColor({255, 255, 255}); - else CCSprite::setColor(col); + if (col == BRONZE_COLOR && Mod::get()->getSettingValue("noBronze")) { + GameObject* gameObj = typeinfo_cast(this); // check for user coin + if (gameObj && gameObj->m_objectID == USER_COIN) { + CCSprite::setColor({255, 255, 255}); + return; + } + } + + CCSprite::setColor(col); } }; -class $modify(LoadingLayer) { - bool init(bool p0) { - swappedTextures = false; - return LoadingLayer::init(p0); +// change end screen +class $modify(EndLevelLayer) { + void customSetup() { + + EndLevelLayer::customSetup(); + if (!Mod::get()->getSettingValue("goldUI")) return; + + // todo: change particle colors + // unfortunately, i can't just trick the game into thinking they're secret coins + // since that changes how it checks for collected coins :( + m_coinsVerified = false; // bronze particles look good enough for now + + removeUITint(m_mainLayer, "coin-1-sprite"); + removeUITint(m_mainLayer, "coin-2-background"); + removeUITint(m_mainLayer, "coin-3-sprite"); + removeUITint(m_mainLayer, "coin-4-background"); + removeUITint(m_mainLayer, "coin-5-sprite"); + removeUITint(m_mainLayer, "coin-6-background"); + + // coin collect effect + for (CCSprite* spr : CCArrayExt(m_coinsToAnimate)) { + spr->setColor(ccWHITE); + } } }; -$execute { - // applies a patch that prevents the game from making the particles in coinEffect.plist silver - // it's somewhere in EnhancedGameObject::updateUserCoin - // first one makes it so (if (isCoin && objectID != 142) { ... }) never runs, 142 is secret coin ID - // second and third changes the coin pickup effect to not be silver for user coins - Mod::get()->patch(reinterpret_cast(geode::base::get() + 0x19c9e8), { 0x83 }); - Mod::get()->patch(reinterpret_cast(geode::base::get() + 0x1a14c1), { 0x74 }); // something 0xc8ffff - Mod::get()->patch(reinterpret_cast(geode::base::get() + 0x1a154d), { 0x74 }); // something concat21 0xffff - - // todo: android support. but that requires arm knowledge -} +// coins in pause menu mod! +class $modify(PauseLayer) { + void customSetup() { + PauseLayer::customSetup(); + if (!Mod::get()->getSettingValue("goldUI") || !Mod::get()->getSettingValue("noBronze")) return; + + auto bottomMenu = getChildByID("bottom-button-menu"); + if (bottomMenu) { + for (auto node : CCArrayExt(bottomMenu->getChildren())) { + CCSprite* spr = static_cast(node); + if (spr->getColor() == BRONZE_COLOR) spr->setColor(ccWHITE); + } + } + } +}; + +// pickup effect +class $modify(GameObject) { + void playDestroyObjectAnim(GJBaseGameLayer* b) { + if (this->m_objectID == USER_COIN) { + this->m_objectType = GameObjectType::SecretCoin; + GameObject::playDestroyObjectAnim(b); + this->m_objectType = GameObjectType::UserCoin; + } + else GameObject::playDestroyObjectAnim(b); + } +}; + +// coin particles +// this is so hacky but it works fine +class $modify(EnhancedGameObject) { + void updateUserCoin() { + if (this->m_objectID == USER_COIN) { + this->m_objectID = GOLD_COIN; + EnhancedGameObject::updateUserCoin(); + this->m_objectID = USER_COIN; + } + else EnhancedGameObject::updateUserCoin(); + } +}; + +// sneaky +class $modify(EditorUI) { + void onCreateObject(int objID) { + // 1614 ID is mini coin + if ((objID == USER_COIN || objID == 1614) && Mod::get()->getSettingValue("goldCoinsEditor") && CCKeyboardDispatcher::get()->getAltKeyPressed()) EditorUI::onCreateObject(GOLD_COIN); + else EditorUI::onCreateObject(objID); + } +}; \ No newline at end of file