diff --git a/Unit testing/billy_objects_tests.cpp b/Unit testing/billy_objects_tests.cpp index e91159b..c19d918 100644 --- a/Unit testing/billy_objects_tests.cpp +++ b/Unit testing/billy_objects_tests.cpp @@ -148,21 +148,7 @@ TEST_CASE("[D] Pushing popping BillyObjects", "[pushpop][0]") { } TEST_CASE("[D] Printing Billy's objects", "[printing]") { - constexpr std::array all_objects{ - weapons::Sword, - weapons::Lance, - weapons::Morgenstern, - weapons::Bow, - equipments::Chainmail, - equipments::CookingPot, - equipments::PamphletTourist, - equipments::MedicKit, - tools::Fourche, - tools::Dagger, - tools::RockClimbingKit, - tools::SackOfGrain, - }; - for (const auto &object: all_objects) { + for (const auto &object: BillyObjects::all_objects) { REQUIRE_NOTHROW(BillyObjects::billy_object_to_string(object)); } } diff --git a/include/billy_objects.hpp b/include/billy_objects.hpp index fcf8c3b..1d47850 100644 --- a/include/billy_objects.hpp +++ b/include/billy_objects.hpp @@ -49,6 +49,21 @@ namespace character { using billyObject = std::variant; using container = ankerl::svector; + static constexpr std::array all_objects{ + weapons::Sword, + weapons::Lance, + weapons::Morgenstern, + weapons::Bow, + equipments::Chainmail, + equipments::CookingPot, + equipments::PamphletTourist, + equipments::MedicKit, + tools::Fourche, + tools::Dagger, + tools::RockClimbingKit, + tools::SackOfGrain, + }; + static constexpr std::string_view json_key{ "billy_objects" }; static constexpr std::string_view sword{ "Sword" }; @@ -76,7 +91,7 @@ namespace character { ~BillyObjects() noexcept = default; - void push_object(const billyObject &object, CharacterSheet &sheet) noexcept; + [[nodiscard]] bool push_object(const billyObject &object, CharacterSheet &sheet) noexcept; void pop_object(CharacterSheet &sheet) noexcept; diff --git a/include/character_sheet.hpp b/include/character_sheet.hpp index cd608b9..b043f0a 100644 --- a/include/character_sheet.hpp +++ b/include/character_sheet.hpp @@ -5,7 +5,9 @@ #include "characteristic/endurance.hpp" #include "characteristic/chance.hpp" #include "characteristic/habilete.hpp" +#include "billy_objects.hpp" #include +#include namespace gui { class Gui; @@ -23,7 +25,7 @@ namespace character { private: friend gui::Gui; - friend class BillyObjects; + friend BillyObjects; std::mt19937_64 engine{ std::random_device{ "rdseed" }() }; @@ -39,6 +41,13 @@ namespace character { characteristic::Habilete habilete; + BillyObjects::container objects; + + std::unordered_set available_objects{ + BillyObjects::all_objects.cbegin(), + BillyObjects::all_objects.cend() + }; + std::uint32_t health_point{ 0 }; std::uint32_t armor{ 0 }; @@ -79,6 +88,8 @@ namespace character { [[nodiscard]] const characteristic::Habilete &get_habilete() const { return habilete; } + [[nodiscard]] const BillyObjects::container &get_objects() const { return objects; } + [[nodiscard]] classe get_current_class() const { if (nb_weapons >= 2) { return classe::Guerrier; @@ -121,6 +132,7 @@ namespace character { j.at("nb_weapons").get_to(billy.nb_weapons); j.at("nb_equipments").get_to(billy.nb_equipments); j.at("nb_tools").get_to(billy.nb_tools); + BillyObjects::from_json(j.at(BillyObjects::json_key), billy.objects); } }; @@ -139,6 +151,8 @@ namespace character { j["nb_weapons"] = billy.get_nb_weapons(); j["nb_equipments"] = billy.get_nb_equipments(); j["nb_tools"] = billy.get_nb_tools(); + j.emplace(std::pair{ BillyObjects::json_key, json::array() }); + BillyObjects::to_json(j.at(BillyObjects::json_key), billy.get_objects()); } } diff --git a/include/gui/gui.hpp b/include/gui/gui.hpp index 60f8284..1e24fe6 100644 --- a/include/gui/gui.hpp +++ b/include/gui/gui.hpp @@ -3,6 +3,7 @@ #include #include "gui/menu/menu.hpp" +#include "billy_objects.hpp" namespace fs = std::filesystem; @@ -24,6 +25,8 @@ namespace gui { private: GuiData &data; + character::BillyObjects deal_objects{}; + menu::Menu menu; const fs::path font; diff --git a/src/billy_objects.cpp b/src/billy_objects.cpp index 872649a..a08be7e 100644 --- a/src/billy_objects.cpp +++ b/src/billy_objects.cpp @@ -17,9 +17,10 @@ constexpr std::uint32_t toolsHash = const_hash("tools"); namespace character { using characteristic::Characteristic; - void BillyObjects::push_object(const billyObject &object, CharacterSheet &sheet) noexcept { + bool BillyObjects::push_object(const billyObject &object, CharacterSheet &sheet) noexcept { if (sheet.objects.size() < 3) { sheet.objects.emplace_back(object); + sheet.available_objects.erase(object); auto &local_habilete = static_cast(sheet.habilete); auto &local_adresse = static_cast(sheet.adresse); @@ -53,13 +54,16 @@ namespace character { plus); }, }, object); + return true; } + return false; } void BillyObjects::pop_object(CharacterSheet &sheet) noexcept { if (!sheet.objects.empty()) { const billyObject obj = sheet.objects.back(); sheet.objects.pop_back(); + sheet.available_objects.insert(obj); auto &local_habilete = static_cast(sheet.habilete); auto &local_adresse = static_cast(sheet.adresse); @@ -109,6 +113,7 @@ namespace character { localEndurance.materiel = operation(localEndurance.materiel, 3); break; case tools::Dagger: + sheet.critique = operation(sheet.critique, 6); break; case tools::RockClimbingKit: localAdresse.materiel = operation(localAdresse.materiel, 1); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 32f3f77..fcb58ef 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -174,32 +174,96 @@ void gui::Gui::stat_second_menu() noexcept { ImGui::EndChild(); } +template +constexpr std::string_view combo_label() { + using character::weapons; + using character::equipments; + using character::tools; + if constexpr (std::is_same_v) { + return "Weapons"; + } else if constexpr (std::is_same_v) { + return "Equipments"; + } else { + return "Tools"; + } +} + +template +constexpr std::string_view material_child_win_id() { + using character::weapons; + using character::equipments; + using character::tools; + if constexpr (std::is_same_v) { + return "weapons"; + } else if constexpr (std::is_same_v) { + return "equipments"; + } else { + return "tools"; + } +} + +template +void generic_combo_menu(character::CharacterSheet &billy, + std::unordered_set &availableObjects, + character::BillyObjects &dealObjects) noexcept { + using character::BillyObjects; + + static auto selected = std::find_if(availableObjects.cbegin(), availableObjects.cend(), [](const auto &billyObj) { + return std::holds_alternative(billyObj); + }); + ImGui::BeginChild(material_child_win_id().data(), + ImVec2(ImGui::GetWindowWidth(), 0), + ImGuiChildFlags_AutoResizeY); + if (ImGui::BeginCombo(combo_label().data(), + BillyObjects::billy_object_to_string(*selected).data(), + ImGuiComboFlags_WidthFitPreview | ImGuiComboFlags_PopupAlignLeft)) { + for (auto iterator = availableObjects.cbegin(); + iterator != availableObjects.cend(); ++iterator) { + if (!std::holds_alternative(*iterator)) { + continue; + } + const bool is_selected = selected == iterator; + + if (ImGui::Selectable(BillyObjects::billy_object_to_string(*iterator).data(), is_selected)) { + selected = iterator; + } + + if (is_selected) { + ImGui::SetItemDefaultFocus(); + } + } + ImGui::EndCombo(); + } + + ImGui::SameLine(); + if (ImGui::Button("+")) { + if (dealObjects.push_object(*selected, billy)) { + selected = std::find_if(availableObjects.cbegin(), + availableObjects.cend(), + [](const auto &billyObj) { return std::holds_alternative(billyObj); }); + } + } + ImGui::EndChild(); +} + void gui::Gui::materiel_menu() noexcept { + using character::BillyObjects; + ImGui::BeginChild("materiel", ImVec2(ImGui::GetWindowWidth() / 3, 0), ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY); ImGui::Text("Matériel"); - ImGui::BeginChild("weapons", ImVec2(0, 0), ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY); - ImGui::Text(character::BillyObjects::sword.data()); - ImGui::Text(character::BillyObjects::lance.data()); - ImGui::Text(character::BillyObjects::morgenstern.data()); - ImGui::Text(character::BillyObjects::bow.data()); - ImGui::EndChild(); + generic_combo_menu(data.billy, data.billy.available_objects, deal_objects); + generic_combo_menu(data.billy, data.billy.available_objects, deal_objects); + generic_combo_menu(data.billy, data.billy.available_objects, deal_objects); - ImGui::BeginChild("equipments", ImVec2(0, 0), ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY); - ImGui::Text(character::BillyObjects::chainmail.data()); - ImGui::Text(character::BillyObjects::cooking_pot.data()); - ImGui::Text(character::BillyObjects::pamphlet_tourist.data()); - ImGui::Text(character::BillyObjects::medic_kit.data()); - ImGui::EndChild(); - - ImGui::BeginChild("tools", ImVec2(0, 0), ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY); - ImGui::Text(character::BillyObjects::fourche.data()); - ImGui::Text(character::BillyObjects::dagger.data()); - ImGui::Text(character::BillyObjects::rock_climbing_kit.data()); - ImGui::Text(character::BillyObjects::sack_of_grain.data()); - ImGui::EndChild(); + for (const auto &object: data.billy.get_objects()) { + ImGui::Text("%s", BillyObjects::billy_object_to_string(object).data()); + } + if (ImGui::Button("Remove last object")) { + deal_objects.pop_object(data.billy); + } ImGui::EndChild(); }