diff --git a/gframe/deck_con.cpp b/gframe/deck_con.cpp index 0c012d844..bca205a56 100644 --- a/gframe/deck_con.cpp +++ b/gframe/deck_con.cpp @@ -200,6 +200,10 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { options.duelFlags = DUEL_MODE_GOAT; break; } + case 8: { + options.duelFlags = DUEL_MODE_GENESYS; + break; + } } #undef CHECK options.duelFlags |= mainGame->chkHandTestNoShuffle->isChecked() ? DUEL_PSEUDO_SHUFFLE : 0; @@ -512,6 +516,14 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { filterList = &gdeckManager->_lfList[mainGame->cbDBLFList->getSelected()]; mainGame->ReloadCBLimit(); StartFilter(true); + if(gGameConfig->enableGenesys) { + if (filterList->listName == L"2025.09 Genesys") { + DeckManager::LoadGenesysPoints(filterList, gdeckManager->GenesysPointList); + } + else { + gdeckManager->GenesysPointList.clear(); + } + } break; } case COMBOBOX_DBDECKS: { @@ -715,7 +727,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { pop_side(hovered_seq); } else { auto pointer = gDataManager->GetCardData(hovered_code); - if(!pointer || (!gGameConfig->ignoreDeckContents && !check_limit(pointer))) + if (!pointer || (!gGameConfig->ignoreDeckContents && !check_limit(pointer))) break; if (event.MouseInput.Shift) { push_side(pointer, -1, gGameConfig->ignoreDeckContents); @@ -752,7 +764,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { if (is_draging) break; auto pointer = gDataManager->GetCardData(hovered_code); - if(!pointer || (!forceInput && !check_limit(pointer))) + if (!pointer || (!forceInput && !check_limit(pointer))) break; if (hovered_pos == 1) { if(!push_main(pointer)) @@ -1240,6 +1252,7 @@ bool DeckBuilder::CheckCardProperties(const CardDataM& data) { count = -1; } else count = flit->second; + switch(filter_lm) { case LIMITATION_FILTER_BANNED: case LIMITATION_FILTER_LIMITED: @@ -1295,6 +1308,12 @@ bool DeckBuilder::CheckCardProperties(const CardDataM& data) { if(data._data.ot != SCOPE_CUSTOM) return false; break; + case LIMITATION_FILTER_GENESYS: + if(gGameConfig->enableGenesys) + if (count != 1) + return false; + break; + default: break; } @@ -1425,6 +1444,8 @@ void DeckBuilder::ClearDeck() { side_monster_count = 0; side_spell_count = 0; side_trap_count = 0; + + genesys_point_count = 0; } void DeckBuilder::RefreshLimitationStatus() { main_and_extra_legend_count_monster = DeckManager::CountLegends(current_deck.main, TYPE_MONSTER) + DeckManager::CountLegends(current_deck.extra, TYPE_MONSTER); @@ -1444,6 +1465,8 @@ void DeckBuilder::RefreshLimitationStatus() { side_monster_count = DeckManager::TypeCount(current_deck.side, TYPE_MONSTER); side_spell_count = DeckManager::TypeCount(current_deck.side, TYPE_SPELL); side_trap_count = DeckManager::TypeCount(current_deck.side, TYPE_TRAP); + + genesys_point_count = DeckManager::GenesysPointCount(current_deck.main, current_deck.extra, current_deck.side); } void DeckBuilder::RefreshLimitationStatusOnRemoved(const CardDataC* card, DeckType location) { switch(location) { @@ -1497,6 +1520,7 @@ void DeckBuilder::RefreshLimitationStatusOnRemoved(const CardDataC* card, DeckTy } } void DeckBuilder::RefreshLimitationStatusOnAdded(const CardDataC* card, DeckType location) { + RemoveGenesysPointCount(card); switch(location) { case DeckType::MAIN: { @@ -1645,6 +1669,14 @@ void DeckBuilder::pop_side(int seq) { } bool DeckBuilder::check_limit(const CardDataC* pointer) { uint32_t limitcode = pointer->alias ? pointer->alias : pointer->code; + + if (filterList->listName.find(L"Genesys (TCG)") != std::wstring::npos) { + + bool check = check_genesys_point_limit(pointer); + + return check; + } + int found = 0; int limit = filterList->whitelist ? 0 : 3; auto endit = filterList->content.end(); @@ -1673,4 +1705,77 @@ void DeckBuilder::RefreshCurrentDeck() { DeckManager::RefreshDeck(current_deck); RefreshLimitationStatus(); } +void DeckBuilder::RemoveGenesysPointCount(const CardDataC* card) { + + if (filterList->listName != L"Genesys (TCG)") { + return; + } + + DeckManager& deckManager = *gdeckManager; + + if (card) { + int cardId = card->code; + auto it = deckManager.GenesysPointList.find(cardId); + if (it != deckManager.GenesysPointList.end()) { + genesys_point_count -= it->second; + } + } +} +void DeckBuilder::AddGenesysPointCount(const CardDataC* card) { + + if (filterList->listName != L"Genesys (TCG)") { + return; + } + + DeckManager& deckManager = *gdeckManager; + + if (card) { + int cardId = card->code; + auto it = deckManager.GenesysPointList.find(cardId); + if (it != deckManager.GenesysPointList.end()) { + genesys_point_count += it->second; + } + } +} + +bool DeckBuilder::check_genesys_point_limit(const CardDataC* pointer) { + uint32_t limitcode = pointer->alias ? pointer->alias : pointer->code; + int limit = 0; + + auto it = filterList->content.find(limitcode); + if (it != filterList->content.end()) { + limit = it->second; + } + else { + limit = 0; + } + // Cause of the banlist system 315 is actuall all 3 point cards + if (limit == 315) { + limit = 3; + } + + int newTotal = genesys_point_count + limit; + + if (newTotal > 100) { + return false; + } + + int found = 0; + limit = 3; + + const auto& deck = current_deck; + for (auto* plist : { &deck.main, &deck.extra, &deck.side }) { + for (auto& pcard : *plist) { + if (pcard->code == limitcode || pcard->alias == limitcode) { + found++; + + if (found >= 3) { + return false; + } + } + } + } + return true; +} + } diff --git a/gframe/deck_con.h b/gframe/deck_con.h index 9268ae8fd..4dc6bcb11 100644 --- a/gframe/deck_con.h +++ b/gframe/deck_con.h @@ -34,7 +34,9 @@ class DeckBuilder final : public irr::IEventReceiver { LIMITATION_FILTER_ILLEGAL, LIMITATION_FILTER_VIDEOGAME, LIMITATION_FILTER_CUSTOM, - LIMITATION_FILTER_ALL + LIMITATION_FILTER_ALL, + + LIMITATION_FILTER_GENESYS, }; enum SEARCH_MODIFIER { SEARCH_MODIFIER_NAME_ONLY = 0x1, @@ -59,6 +61,12 @@ class DeckBuilder final : public irr::IEventReceiver { } void StartFilter(bool force_refresh = false); void RefreshCurrentDeck(); + + + void RemoveGenesysPointCount(const CardDataC* card); + void AddGenesysPointCount(const CardDataC* card); + bool check_genesys_point_limit(const CardDataC* pointer); + static void ClearGenesysPointCount(); private: void GetHoveredCard(); bool FiltersChanged(); @@ -146,6 +154,8 @@ class DeckBuilder final : public irr::IEventReceiver { std::map, std::less<>> searched_terms; std::vector results; std::wstring result_string; + + uint16_t genesys_point_count; }; } diff --git a/gframe/deck_manager.cpp b/gframe/deck_manager.cpp index 09245d1ca..47f681fe3 100644 --- a/gframe/deck_manager.cpp +++ b/gframe/deck_manager.cpp @@ -213,6 +213,11 @@ DeckError DeckManager::CheckDeckContent(const Deck& deck, LFList const* lflist, return ret.type = DeckError::TOOMANYLEGENDS, ret; if(TypeCount(deck.main, TYPE_SKILL) > 1) return ret.type = DeckError::TOOMANYSKILLS, ret; + + //NEEDS TO BE CHANGED + if (lflist->listName == L"2025.09 Genesys" && GenesysPointCount(deck.main, deck.extra, deck.side) > 100) + return ret.type = DeckError::TOOMANYPOINTS, ret; + banlist_content_t ccount; if(!lflist) return ret; @@ -601,4 +606,40 @@ bool DeckManager::DeleteDeck([[maybe_unused]] Deck& deck, epro::path_stringview bool DeckManager::RenameDeck(epro::path_stringview oldname, epro::path_stringview newname) { return Utils::FileMove(GetDeckPath(oldname), GetDeckPath(newname)); } + +int DeckManager::GenesysPointCount(const Deck::Vector& mainDeck, const Deck::Vector& extraDeck, const Deck::Vector& sideDeck) { + + DeckManager& deckManager = *gdeckManager; + + ygo::Deck::Vector CardsInEntireDeck; + + CardsInEntireDeck.insert(CardsInEntireDeck.end(), mainDeck.begin(), mainDeck.end()); + CardsInEntireDeck.insert(CardsInEntireDeck.end(), extraDeck.begin(), extraDeck.end()); + CardsInEntireDeck.insert(CardsInEntireDeck.end(), sideDeck.begin(), sideDeck.end()); + + int points = 0; + for (const auto& card : CardsInEntireDeck) { + if (card) { + int cardId = card->code; + auto it = deckManager.GenesysPointList.find(cardId); + if (it != deckManager.GenesysPointList.end()) { + points += it->second; + } + } + } + return points; +} + +void DeckManager::LoadGenesysPoints(LFList* banlist, std::unordered_map& pointsMap) +{ + pointsMap.clear(); + + for (const auto& card : banlist->content) { + int cardId = card.first; + int points = card.second; + if (points > 0) { + pointsMap[cardId] = points; + } + } +} } diff --git a/gframe/deck_manager.h b/gframe/deck_manager.h index 49bd0daed..327f8c2ab 100644 --- a/gframe/deck_manager.h +++ b/gframe/deck_manager.h @@ -87,6 +87,10 @@ class DeckManager { static bool ImportDeckBase64Omega(Deck& deck, epro::wstringview buffer); static bool DeleteDeck(Deck& deck, epro::path_stringview name); static bool RenameDeck(epro::path_stringview oldname, epro::path_stringview newname); + + static int GenesysPointCount(const Deck::Vector& mainDeck, const Deck::Vector& extraDeck, const Deck::Vector& sideDeck); + static void LoadGenesysPoints(LFList* banlist, std::unordered_map& pointsMap); + std::unordered_map GenesysPointList; }; extern DeckManager* gdeckManager; diff --git a/gframe/drawing.cpp b/gframe/drawing.cpp index 918406c7a..a94756dc1 100644 --- a/gframe/drawing.cpp +++ b/gframe/drawing.cpp @@ -1266,6 +1266,25 @@ void Game::DrawDeckBd() { const auto main_deck_size_str = GetDeckSizeStr(current_deck.main, gdeckManager->pre_deck.main); DrawShadowText(numFont, main_deck_size_str, Resize(379, 137, 439, 157), Resize(1, 1, 1, 1), 0xffffffff, 0xff000000, false, true); + + //SHOW GENESYS POINTS IF ENABLED + if (gSettings.chkEnableGenesys->isChecked()) { + + const auto genesys_points = epro::format(L"{} / 100", deckBuilder.genesys_point_count); + + DrawShadowText(textFont, gDataManager->GetSysString(12126), Resize(415, 136, 550, 156), Resize(1, 1, 1, 1), 0xffffffff, 0xff000000, false, true); + + const auto genesyspos = Resize(314, 136, 580, 156); + const auto genesysSize = textFont->getDimensionustring(genesys_points); + const auto genesys_pos = irr::core::recti(genesyspos.LowerRightCorner.X - genesysSize.Width - 5, genesyspos.UpperLeftCorner.Y, + genesyspos.LowerRightCorner.X, genesyspos.LowerRightCorner.Y); + + DrawShadowText(textFont, genesys_points, genesys_pos, irr::core::recti{ 1, 1, 1, 1 }, 0xffffffff, 0xff000000, false, true); + + } + + + const auto main_types_count_str = epro::format(L"{} {} {} {} {} {}", gDataManager->GetSysString(1312), deckBuilder.main_monster_count, gDataManager->GetSysString(1313), deckBuilder.main_spell_count, diff --git a/gframe/duelclient.cpp b/gframe/duelclient.cpp index 82a0b4f6d..889ed38fb 100644 --- a/gframe/duelclient.cpp +++ b/gframe/duelclient.cpp @@ -540,6 +540,10 @@ void DuelClient::HandleSTOCPacketLanAsync(const std::vector& data) { text = gDataManager->GetSysString(1427).data(); break; } + case DeckError::TOOMANYPOINTS: { + text = gDataManager->GetSysString(12229).data(); + break; + } default: { text = gDataManager->GetSysString(1406).data(); break; diff --git a/gframe/event_handler.cpp b/gframe/event_handler.cpp index fcfaec00f..ec83d8626 100644 --- a/gframe/event_handler.cpp +++ b/gframe/event_handler.cpp @@ -1974,6 +1974,10 @@ bool ClientField::OnCommonEvent(const irr::SEvent& event, bool& stopPropagation) gGameConfig->ignoreDeckContents = mainGame->gSettings.chkIgnoreDeckContents->isChecked(); return true; } + case CHECKBOX_ENABLE_GENESYS: { + gGameConfig->enableGenesys = mainGame->gSettings.chkEnableGenesys->isChecked(); + return true; + } case CHECKBOX_ADD_CARD_NAME_TO_DECK_LIST: { gGameConfig->addCardNamesToDeckList = mainGame->gSettings.chkAddCardNamesInDeckList->isChecked(); return true; diff --git a/gframe/game.cpp b/gframe/game.cpp index d3af1643c..34ff34633 100644 --- a/gframe/game.cpp +++ b/gframe/game.cpp @@ -1586,6 +1586,9 @@ void Game::PopulateTabSettingsWindow() { tabSettings.chkIgnoreDeckContents = env->addCheckBox(gGameConfig->ignoreDeckContents, GetNextRect(), tabPanel, CHECKBOX_IGNORE_DECK_CONTENTS, gDataManager->GetSysString(12119).data()); menuHandler.MakeElementSynchronized(tabSettings.chkIgnoreDeckContents); defaultStrings.emplace_back(tabSettings.chkIgnoreDeckContents, 12119); + tabSettings.chkEnableGenesysDeckBuilding = env->addCheckBox(gGameConfig->enableGenesys, GetNextRect(), tabPanel, CHECKBOX_ENABLE_GENESYS, gDataManager->GetSysString(12127).data()); + menuHandler.MakeElementSynchronized(tabSettings.chkEnableGenesysDeckBuilding); + defaultStrings.emplace_back(tabSettings.chkEnableGenesysDeckBuilding, 12127); // Check OnResize for button placement information cur_y += 5; btnTabShowSettings = env->addButton(GetNextRect(), tabPanel, BUTTON_SHOW_SETTINGS, gDataManager->GetSysString(2059).data()); @@ -1696,6 +1699,8 @@ void Game::PopulateSettingsWindow() { defaultStrings.emplace_back(gSettings.chkIgnoreDeckContents, 12119); gSettings.chkAddCardNamesInDeckList = env->addCheckBox(gGameConfig->addCardNamesToDeckList, GetNextRect(), sPanel, CHECKBOX_ADD_CARD_NAME_TO_DECK_LIST, gDataManager->GetSysString(12123).data()); defaultStrings.emplace_back(gSettings.chkAddCardNamesInDeckList, 12123); + gSettings.chkEnableGenesys = env->addCheckBox(gGameConfig->enableGenesys, GetNextRect(), sPanel, CHECKBOX_ENABLE_GENESYS, gDataManager->GetSysString(12127).data()); + defaultStrings.emplace_back(gSettings.chkEnableGenesys, 12127); } { @@ -3150,6 +3155,13 @@ void Game::UpdateDuelParam() { break; } } + case DUEL_MODE_GENESYS: { + cbDuelRule->setSelected(8); + if (flag2 == DUEL_MODE_MR2_FORB) { + cbDuelRule->removeItem(9); + break; + } + } [[fallthrough]]; default: switch(flag & ~DUEL_TCG_SEGOC_NONPUBLIC) { @@ -3467,6 +3479,11 @@ void Game::ReloadCBLimit() { cbLimit->addItem(gDataManager->GetSysString(1267).data(), DeckBuilder::LIMITATION_FILTER_VIDEOGAME); cbLimit->addItem(gDataManager->GetSysString(1268).data(), DeckBuilder::LIMITATION_FILTER_CUSTOM); } + if (gSettings.chkEnableGenesys->isChecked()) { + cbLimit->clear(); + cbLimit->addItem(gDataManager->GetSysString(1320).data(), DeckBuilder::LIMITATION_FILTER_UNLIMITED); + cbLimit->addItem(gDataManager->GetSysString(12231).data(), DeckBuilder::LIMITATION_FILTER_GENESYS); + } } else { chkAnime->setEnabled(false); cbLimit->addItem(gDataManager->GetSysString(1912).data(), DeckBuilder::LIMITATION_FILTER_LEGEND); @@ -3512,6 +3529,7 @@ void Game::ReloadCBDuelRule(irr::gui::IGUIComboBox* cb) { cb->addItem(gDataManager->GetSysString(1258).data()); cb->addItem(gDataManager->GetSysString(1259).data()); cb->addItem(gDataManager->GetSysString(1248).data()); + cb->addItem(gDataManager->GetSysString(12230).data()); } void Game::ReloadCBRule() { cbRule->clear(); diff --git a/gframe/game_config.inl b/gframe/game_config.inl index 5ea99b946..5fcaa5ab0 100644 --- a/gframe/game_config.inl +++ b/gframe/game_config.inl @@ -34,6 +34,7 @@ OPTION(bool, noShuffleDeck, false) OPTION(bool, noCheckDeckContent, false) OPTION(bool, noCheckDeckSize, false) OPTION(bool, hideHandsInReplays, false) +OPTION(bool, enableGenesys, false) OPTION(ygo::GameConfig::TextFont, textfont, EPRO_TEXT("fonts/NotoSansJP-Regular.otf"), 12) OPTION(epro::path_string, numfont, EPRO_TEXT("fonts/NotoSansJP-Regular.otf")) #ifdef YGOPRO_USE_BUNDLED_FONT diff --git a/gframe/menu_handler.h b/gframe/menu_handler.h index 553686467..1debeaafd 100644 --- a/gframe/menu_handler.h +++ b/gframe/menu_handler.h @@ -290,6 +290,8 @@ enum GUI { DONT_CHECK_DECK_CONTENT, DONT_CHECK_DECK_SIZE, DONT_SHUFFLE_DECK, + + CHECKBOX_ENABLE_GENESYS, }; class MenuHandler final : public irr::IEventReceiver { diff --git a/gframe/network.h b/gframe/network.h index 3961eaa7a..17760b6a5 100644 --- a/gframe/network.h +++ b/gframe/network.h @@ -121,7 +121,8 @@ struct DeckError { UNOFFICIALCARD, INVALIDSIZE, TOOMANYLEGENDS, - TOOMANYSKILLS + TOOMANYSKILLS, + TOOMANYPOINTS }; DERR_TYPE type = DERR_TYPE::NONE; struct { diff --git a/gframe/ocgapi_constants.h b/gframe/ocgapi_constants.h index cdc0f4c03..9e593f359 100644 --- a/gframe/ocgapi_constants.h +++ b/gframe/ocgapi_constants.h @@ -426,6 +426,7 @@ #define DUEL_MODE_MR3_FORB TYPE_LINK #define DUEL_MODE_MR4_FORB 0 #define DUEL_MODE_MR5_FORB 0 +#define DUEL_MODE_GENESYS (DUEL_TRAP_MONSTERS_NOT_USE_ZONE | DUEL_TRIGGER_ONLY_IN_LOCATION) #endif /* OCGAPI_CONSTANTS_H */ diff --git a/gframe/settings_window.h b/gframe/settings_window.h index 3b0ca4970..495b84428 100644 --- a/gframe/settings_window.h +++ b/gframe/settings_window.h @@ -41,6 +41,8 @@ struct SettingsPane { irr::gui::IGUICheckBox* chkIgnoreDeckContents; + irr::gui::IGUICheckBox* chkEnableGenesysDeckBuilding; + void DisableAudio(); }; @@ -71,6 +73,7 @@ struct SettingsWindow { irr::gui::IGUICheckBox* chkConfirmDeckClear; irr::gui::IGUICheckBox* chkIgnoreDeckContents; irr::gui::IGUICheckBox* chkAddCardNamesInDeckList; + irr::gui::IGUICheckBox* chkEnableGenesys; SettingsTab duel; irr::gui::IGUICheckBox* chkIgnoreOpponents;