From 933c0c49b92cc7304f370dffe8646b49113f9d45 Mon Sep 17 00:00:00 2001 From: Edoardo Lolletti Date: Thu, 20 Apr 2023 23:19:48 +0200 Subject: [PATCH] Update handling of race selection Make the race selection dialog no longer use an hardcoded max amount of checkboxes and update its drawing so that all the options are put one after the other rather than having big gaps between the available ones. --- gframe/client_field.cpp | 15 +++++++++++++++ gframe/client_field.h | 1 + gframe/common.h | 8 +++++++- gframe/data_manager.cpp | 13 ++----------- gframe/data_manager.h | 7 +++++++ gframe/duelclient.cpp | 15 ++++----------- gframe/event_handler.cpp | 2 +- gframe/game.cpp | 19 +++++++++++-------- gframe/game.h | 2 +- 9 files changed, 49 insertions(+), 33 deletions(-) diff --git a/gframe/client_field.cpp b/gframe/client_field.cpp index 1829d65a5..fe7fd1c67 100644 --- a/gframe/client_field.cpp +++ b/gframe/client_field.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include "game.h" @@ -1157,6 +1158,20 @@ bool ClientField::CheckSelectSum() { return ret; } } +void ClientField::ShowSelectRace(uint64_t race) { + uint64_t filter = 0x1; + auto selected = 0; + for(auto i = 0u; i < sizeofarr(mainGame->chkRace); ++i, filter <<= 1) { + auto* checkBox = mainGame->chkRace[i]; + checkBox->setChecked(false); + auto checked = (filter & race) != 0; + checkBox->setVisible(checked); + if(checked) { + checkBox->setRelativePosition(mainGame->Scale(10 + (selected % 3) * 120, (selected / 3) * 25, 150 + (selected % 3) * 120, 25 + (selected / 3) * 25)); + ++selected; + } + } +} bool ClientField::check_min(const std::set& left, std::set::const_iterator index, int min, int max) { if (index == left.end()) return false; diff --git a/gframe/client_field.h b/gframe/client_field.h index 34b0632ee..358c26c44 100644 --- a/gframe/client_field.h +++ b/gframe/client_field.h @@ -113,6 +113,7 @@ class ClientField: public irr::IEventReceiver { void FadeCard(ClientCard* pcard, float alpha, float frame); bool ShowSelectSum(); bool CheckSelectSum(); + void ShowSelectRace(uint64_t race); bool check_min(const std::set& left, std::set::const_iterator index, int min, int max); bool check_sel_sum_s(const std::set& left, size_t index, int acc); void check_sel_sum_t(const std::set& left, int acc); diff --git a/gframe/common.h b/gframe/common.h index f4202644f..7067bb0b9 100644 --- a/gframe/common.h +++ b/gframe/common.h @@ -111,7 +111,13 @@ #define RACE_CREATORGOD 0x400000 #define RACE_WYRM 0x800000 #define RACE_CYBERSE 0x1000000 -#define RACE_CYBORG 0x2000000 +#define RACE_ILLUSIONIST 0x2000000 +#define RACE_CYBORG 0x4000000 +#define RACE_MAGICALKNIGHT 0x8000000 +#define RACE_HIGHDRAGON 0x10000000 +#define RACE_OMEGAPSYCHIC 0x20000000 +#define RACE_CELESTIALWARRIOR 0x40000000 +#define RACE_GALAXY 0x80000000 //Reasons #define REASON_DESTROY 0x1 diff --git a/gframe/data_manager.cpp b/gframe/data_manager.cpp index a182f2cc1..c6903c8d4 100644 --- a/gframe/data_manager.cpp +++ b/gframe/data_manager.cpp @@ -466,20 +466,11 @@ static std::wstring FormatSkill(uint64_t skill_type) { std::wstring DataManager::FormatRace(uint64_t race, bool isSkill) const { if(isSkill) return FormatSkill(race); std::wstring res; - uint32_t i = 1020; - for(; race && i <= 1049; race >>= 1, ++i) { + for(uint32_t i = 0; race; race >>= 1, ++i) { if(race & 0x1u) { if(!res.empty()) res += L'|'; - appendstring(res, GetSysString(i)); - } - } - //strings 1050 above are already used, read the rest from this other range - for(i = 2500; race; race >>= 1, ++i) { - if(race & 0x1u) { - if(!res.empty()) - res += L'|'; - appendstring(res, GetSysString(i)); + appendstring(res, GetSysString(GetRaceStringIndex(i))); } } if(res.empty()) diff --git a/gframe/data_manager.h b/gframe/data_manager.h index 9a7428ec8..3fd681fc4 100644 --- a/gframe/data_manager.h +++ b/gframe/data_manager.h @@ -4,6 +4,7 @@ #include #include #include +#include "common.h" #include "text_types.h" #include "utils.h" @@ -138,6 +139,12 @@ class DataManager { inline epro::wstringview GetSetName(uint32_t code) const { return _setnameStrings.GetLocale(code, L""); } + inline uint32_t GetRaceStringIndex(uint32_t race_idx) const { + if(race_idx < 30) + return 1020 + race_idx; + //strings 1050 above are already used, read the rest from this other range + return (2500 - 30) + race_idx; + } std::vector GetSetCode(const std::vector& setname) const; std::wstring GetNumString(size_t num, bool bracket = false) const; epro::wstringview FormatLocation(uint32_t location, int sequence) const; diff --git a/gframe/duelclient.cpp b/gframe/duelclient.cpp index b839e41bf..b65258464 100644 --- a/gframe/duelclient.cpp +++ b/gframe/duelclient.cpp @@ -3834,14 +3834,8 @@ int DuelClient::ClientAnalyze(const uint8_t* msg, uint32_t len) { /*const auto player = */mainGame->LocalPlayer(BufferIO::Read(pbuf)); mainGame->dField.announce_count = BufferIO::Read(pbuf); const auto available = CompatRead(pbuf); - uint64_t filter = 0x1; - for(int i = 0; i < 25; ++i, filter <<= 1) { - mainGame->chkRace[i]->setChecked(false); - if(filter & available) - mainGame->chkRace[i]->setVisible(true); - else mainGame->chkRace[i]->setVisible(false); - } std::unique_lock lock(mainGame->gMutex); + mainGame->dField.ShowSelectRace(available); mainGame->wANRace->setText(gDataManager->GetDesc(select_hint ? select_hint : 563, mainGame->dInfo.compat_mode).data()); mainGame->PopupElement(mainGame->wANRace); select_hint = 0; @@ -3851,11 +3845,10 @@ int DuelClient::ClientAnalyze(const uint8_t* msg, uint32_t len) { /*const auto player = */mainGame->LocalPlayer(BufferIO::Read(pbuf)); mainGame->dField.announce_count = BufferIO::Read(pbuf); const auto available = BufferIO::Read(pbuf); - for(int i = 0, filter = 0x1; i < 7; ++i, filter <<= 1) { + uint32_t filter = 0x1; + for(auto i = 0u; i < sizeofarr(mainGame->chkAttribute); ++i, filter <<= 1) { mainGame->chkAttribute[i]->setChecked(false); - if(filter & available) - mainGame->chkAttribute[i]->setVisible(true); - else mainGame->chkAttribute[i]->setVisible(false); + mainGame->chkAttribute[i]->setVisible((filter& available) != 0); } std::unique_lock lock(mainGame->gMutex); mainGame->wANAttribute->setText(gDataManager->GetDesc(select_hint ? select_hint : 562, mainGame->dInfo.compat_mode).data()); diff --git a/gframe/event_handler.cpp b/gframe/event_handler.cpp index a400525ce..7c5e27539 100644 --- a/gframe/event_handler.cpp +++ b/gframe/event_handler.cpp @@ -857,7 +857,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) { } case CHECK_RACE: { uint64_t rac = 0, filter = 0x1, count = 0; - for(int i = 0; i < 25; ++i, filter <<= 1) { + for(int i = 0; i < sizeofarr(mainGame->chkRace); ++i, filter <<= 1) { if(mainGame->chkRace[i]->isChecked()) { rac |= filter; count++; diff --git a/gframe/game.cpp b/gframe/game.cpp index 01c653e39..b737617ed 100644 --- a/gframe/game.cpp +++ b/gframe/game.cpp @@ -510,10 +510,15 @@ void Game::Initialize() { defaultStrings.emplace_back(wANRace, 563); wANRace->getCloseButton()->setVisible(false); wANRace->setVisible(false); - for(int i = 0; i < 25; ++i) { - chkRace[i] = env->addCheckBox(false, Scale(10 + (i % 4) * 90, 25 + (i / 4) * 25, 100 + (i % 4) * 90, 50 + (i / 4) * 25), - wANRace, CHECK_RACE, gDataManager->GetSysString(1020 + i).data()); - defaultStrings.emplace_back(chkRace[i], 1020 + i); + { + auto tmpPanel = irr::gui::Panel::addPanel(env, wANRace, -1, wANRace->getClientRect(), true, false); + auto crPanel = tmpPanel->getSubpanel(); + for(int i = 0; i < static_cast(sizeofarr(chkRace)); ++i) { + auto string = gDataManager->GetRaceStringIndex(i); + chkRace[i] = env->addCheckBox(false, Scale(10 + (i % 3) * 120, (i / 3) * 25, 150 + (i % 3) * 120, 25 + (i / 3) * 25), + crPanel, CHECK_RACE, gDataManager->GetSysString(string).data()); + defaultStrings.emplace_back(chkRace[i], string); + } } //selection hint stHintMsg = env->addStaticText(L"", Scale(500, 60, 820, 90), true, false, 0, -1, false); @@ -3425,10 +3430,8 @@ void Game::ReloadCBRace() { //currently corresponding to RACE_GALAXY static constexpr auto RACE_MAX = UINT64_C(0x80000000); uint64_t filter = 0x1; - for(uint32_t i = 1020; i <= 1049 && filter <= RACE_MAX; i++, filter <<= 1) - cbRace->addItem(gDataManager->GetSysString(i).data(), filter); - for(uint32_t i = 2500; filter <= RACE_MAX; i++, filter <<= 1) - cbRace->addItem(gDataManager->GetSysString(i).data(), filter); + for(uint32_t i = 0; filter <= RACE_MAX; i++, filter <<= 1) + cbRace->addItem(gDataManager->GetSysString(gDataManager->GetRaceStringIndex(i)).data(), filter); } void Game::ReloadCBFilterRule() { cbFilterRule->clear(); diff --git a/gframe/game.h b/gframe/game.h index c98771172..df2385bd8 100644 --- a/gframe/game.h +++ b/gframe/game.h @@ -591,7 +591,7 @@ class Game { irr::gui::IGUICheckBox* chkAttribute[7]; //announce race irr::gui::IGUIWindow* wANRace; - irr::gui::IGUICheckBox* chkRace[25]; + irr::gui::IGUICheckBox* chkRace[64]; //cmd menu irr::gui::IGUIWindow* wCmdMenu; irr::gui::IGUIButton* btnActivate;