From fb6f902f280862862d57fd17b01f2b7e68b5b0f9 Mon Sep 17 00:00:00 2001 From: shweet Date: Tue, 17 Mar 2026 04:05:04 -0400 Subject: [PATCH] Inventory updates, API updates, lots of file renaming --- CMakeLists.txt | 4 +- src/entity/actor.hpp | 2 +- src/entity/character.cpp | 3 + src/entity/character.hpp | 1 + src/entity/cursor.hpp | 5 +- src/{ => render}/canvas.cpp | 4 +- src/{ => render}/canvas.hpp | 2 +- src/resource/xml/character.cpp | 22 +- src/resource/xml/character.hpp | 11 +- src/resource/xml/character_preview.cpp | 1 + src/resource/xml/character_preview.hpp | 2 + src/resource/xml/item.cpp | 4 +- src/resource/xml/item.hpp | 4 +- src/resource/xml/save.cpp | 18 +- src/resource/xml/settings.cpp | 25 +- src/resource/xml/settings.hpp | 1 + .../xml/{play.cpp => skill_check.cpp} | 8 +- .../xml/{play.hpp => skill_check.hpp} | 6 +- src/resource/xml/util.cpp | 157 ++++++-- src/resource/xml/util.hpp | 49 ++- src/state.cpp | 34 +- src/state.hpp | 8 +- src/state/main/inventory.cpp | 228 ------------ src/state/{main.cpp => play.cpp} | 99 ++--- src/state/{main.hpp => play.hpp} | 48 +-- .../play.cpp => play/arcade/skill_check.cpp} | 30 +- .../play.hpp => play/arcade/skill_check.hpp} | 20 +- src/state/{main => play}/area_manager.cpp | 2 +- src/state/{main => play}/area_manager.hpp | 2 +- .../{main => play}/character_manager.cpp | 19 +- .../{main => play}/character_manager.hpp | 6 +- src/state/{main => play}/chat.cpp | 2 +- src/state/{main => play}/chat.hpp | 2 +- src/state/{main => play}/cheats.cpp | 2 +- src/state/{main => play}/cheats.hpp | 2 +- src/state/{main => play}/debug.cpp | 2 +- src/state/{main => play}/debug.hpp | 2 +- src/state/{main => play}/info.cpp | 2 +- src/state/{main => play}/info.hpp | 2 +- src/state/play/inventory.cpp | 348 ++++++++++++++++++ src/state/{main => play}/inventory.hpp | 3 +- src/state/{main => play}/item_manager.cpp | 2 +- src/state/{main => play}/item_manager.hpp | 2 +- src/state/{main => play}/menu.cpp | 25 +- src/state/{main => play}/menu.hpp | 17 +- src/state/{main => play}/stats.cpp | 20 +- src/state/{main => play}/stats.hpp | 6 +- src/state/{main => play}/text.cpp | 2 +- src/state/{main => play}/text.hpp | 2 +- src/state/{main => play}/toasts.cpp | 2 +- src/state/{main => play}/toasts.hpp | 2 +- src/state/{main => play}/tools.cpp | 13 +- src/state/{main => play}/tools.hpp | 2 +- src/state/{main => play}/world.cpp | 2 +- src/state/{main => play}/world.hpp | 4 +- src/state/select.hpp | 4 +- src/state/select/characters.cpp | 11 +- src/state/select/characters.hpp | 6 +- src/state/select/info.cpp | 5 +- src/state/select/preview.cpp | 7 +- .../{configuration.cpp => settings_menu.cpp} | 16 +- .../{configuration.hpp => settings_menu.hpp} | 7 +- src/util/interact_type.hpp | 24 -- 63 files changed, 820 insertions(+), 553 deletions(-) rename src/{ => render}/canvas.cpp (99%) rename src/{ => render}/canvas.hpp (98%) rename src/resource/xml/{play.cpp => skill_check.cpp} (91%) rename src/resource/xml/{play.hpp => skill_check.hpp} (90%) delete mode 100644 src/state/main/inventory.cpp rename src/state/{main.cpp => play.cpp} (81%) rename src/state/{main.hpp => play.hpp} (51%) rename src/state/{main/play.cpp => play/arcade/skill_check.cpp} (94%) rename src/state/{main/play.hpp => play/arcade/skill_check.hpp} (81%) rename src/state/{main => play}/area_manager.cpp (94%) rename src/state/{main => play}/area_manager.hpp (82%) rename src/state/{main => play}/character_manager.cpp (86%) rename src/state/{main => play}/character_manager.hpp (79%) rename src/state/{main => play}/chat.cpp (97%) rename src/state/{main => play}/chat.hpp (84%) rename src/state/{main => play}/cheats.cpp (99%) rename src/state/{main => play}/cheats.hpp (86%) rename src/state/{main => play}/debug.cpp (97%) rename src/state/{main => play}/debug.hpp (91%) rename src/state/{main => play}/info.cpp (99%) rename src/state/{main => play}/info.hpp (87%) create mode 100644 src/state/play/inventory.cpp rename src/state/{main => play}/inventory.hpp (89%) rename src/state/{main => play}/item_manager.cpp (99%) rename src/state/{main => play}/item_manager.hpp (97%) rename src/state/{main => play}/menu.cpp (86%) rename src/state/{main => play}/menu.hpp (69%) rename src/state/{main => play}/stats.cpp (61%) rename src/state/{main => play}/stats.hpp (53%) rename src/state/{main => play}/text.cpp (99%) rename src/state/{main => play}/text.hpp (94%) rename src/state/{main => play}/toasts.cpp (98%) rename src/state/{main => play}/toasts.hpp (91%) rename src/state/{main => play}/tools.cpp (90%) rename src/state/{main => play}/tools.hpp (91%) rename src/state/{main => play}/world.cpp (99%) rename src/state/{main => play}/world.hpp (93%) rename src/state/{configuration.cpp => settings_menu.cpp} (79%) rename src/state/{configuration.hpp => settings_menu.hpp} (78%) delete mode 100644 src/util/interact_type.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d8ea17..beedec8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,10 +109,12 @@ set (TINYXML2_SOURCES ${TINYXML2_DIR}/tinyxml2.cpp) file(GLOB PROJECT_SRC CONFIGURE_DEPENDS include/*.cpp src/*.cpp + src/render/*.cpp src/resource/*.cpp src/resource/xml/*.cpp src/state/*.cpp - src/state/main/*.cpp + src/state/play/*.cpp + src/state/play/arcade/*.cpp src/state/select/*.cpp src/entity/*.cpp src/window/*.cpp diff --git a/src/entity/actor.hpp b/src/entity/actor.hpp index f30455c..1c21833 100644 --- a/src/entity/actor.hpp +++ b/src/entity/actor.hpp @@ -2,7 +2,7 @@ #include -#include "../canvas.hpp" +#include "../render/canvas.hpp" #include "../resource/xml/anm2.hpp" namespace game::entity diff --git a/src/entity/character.cpp b/src/entity/character.cpp index 376aa21..2de063d 100644 --- a/src/entity/character.cpp +++ b/src/entity/character.cpp @@ -335,12 +335,14 @@ namespace game::entity void Character::queue_play(QueuedPlay play) { + if (isStageUp) return; queuedPlay = play; queuedPlay.animation = animation_name_convert(queuedPlay.animation); } void Character::queue_idle_animation() { + if (isStageUp) return; if (data.animations.idle.empty()) return; queue_play( {is_over_capacity() && !data.animations.idleFull.empty() ? data.animations.idleFull : data.animations.idle}); @@ -348,6 +350,7 @@ namespace game::entity void Character::queue_interact_area_animation(resource::xml::Character::InteractArea& interactArea) { + if (isStageUp) return; if (interactArea.animation.empty()) return; queue_play({is_over_capacity() && !interactArea.animationFull.empty() ? interactArea.animationFull : interactArea.animation}); diff --git a/src/entity/character.hpp b/src/entity/character.hpp index 76b8c77..ee9daee 100644 --- a/src/entity/character.hpp +++ b/src/entity/character.hpp @@ -47,6 +47,7 @@ namespace game::entity std::vector animationBlinkDurations{}; bool isStageUp{}; + bool isStageUpDuring{}; bool isJustStageUp{}; bool isJustStageFinal{}; diff --git a/src/entity/cursor.hpp b/src/entity/cursor.hpp index a7fec19..8fdd473 100644 --- a/src/entity/cursor.hpp +++ b/src/entity/cursor.hpp @@ -1,6 +1,5 @@ #pragma once -#include "../util/interact_type.hpp" #include "actor.hpp" namespace game::entity @@ -16,11 +15,11 @@ namespace game::entity }; State state{DEFAULT}; - InteractType mode{InteractType::RUB}; + int interactTypeID{-1}; Cursor() = default; Cursor(resource::xml::Anm2&); void tick(); void update(); }; -} \ No newline at end of file +} diff --git a/src/canvas.cpp b/src/render/canvas.cpp similarity index 99% rename from src/canvas.cpp rename to src/render/canvas.cpp index 7d5d84a..d4be7c2 100644 --- a/src/canvas.cpp +++ b/src/render/canvas.cpp @@ -3,8 +3,8 @@ #include -#include "util/imgui.hpp" -#include "util/math.hpp" +#include "../util/imgui.hpp" +#include "../util/math.hpp" using namespace glm; using namespace game::resource; diff --git a/src/canvas.hpp b/src/render/canvas.hpp similarity index 98% rename from src/canvas.hpp rename to src/render/canvas.hpp index 8c4ef53..2343480 100644 --- a/src/canvas.hpp +++ b/src/render/canvas.hpp @@ -6,7 +6,7 @@ #include #endif -#include "resource/shader.hpp" +#include "../resource/shader.hpp" #include #include #include diff --git a/src/resource/xml/character.cpp b/src/resource/xml/character.cpp index d8eada5..6c94ba9 100644 --- a/src/resource/xml/character.cpp +++ b/src/resource/xml/character.cpp @@ -41,6 +41,8 @@ namespace game::resource::xml query_anm2(root, "Anm2", archive, textureRootPath, anm2); query_string_attribute(root, "Name", &name); + query_vec3(root, "ColorR", "ColorG", "ColorB", color); + root->QueryFloatAttribute("Weight", &weight); root->QueryFloatAttribute("Capacity", &capacity); @@ -159,6 +161,15 @@ namespace game::resource::xml if (auto element = root->FirstChildElement("InteractAreas")) { + auto interact_type_id_get = [&](const std::string& typeName) + { + for (int i = 0; i < (int)interactTypeNames.size(); i++) + if (interactTypeNames[i] == typeName) return i; + + interactTypeNames.emplace_back(typeName); + return (int)interactTypeNames.size() - 1; + }; + for (auto child = element->FirstChildElement("InteractArea"); child; child = child->NextSiblingElement("InteractArea")) { @@ -173,6 +184,7 @@ namespace game::resource::xml query_string_attribute(child, "AnimationCursorActive", &interactArea.animationCursorActive); query_sound_entry_collection(child, "Sound", archive, soundRootPath, interactArea.sound, "Path"); dialogue.query_pool_id(child, "DialoguePoolID", interactArea.pool.id); + query_bool_attribute(child, "IsHold", &interactArea.isHold); child->QueryFloatAttribute("DigestionBonusRub", &interactArea.digestionBonusRub); child->QueryFloatAttribute("DigestionBonusClick", &interactArea.digestionBonusClick); child->QueryFloatAttribute("Time", &interactArea.time); @@ -181,9 +193,7 @@ namespace game::resource::xml std::string typeString{}; query_string_attribute(child, "Type", &typeString); - - for (int i = 0; i < (int)std::size(INTERACT_TYPE_STRINGS); i++) - if (typeString == INTERACT_TYPE_STRINGS[i]) interactArea.type = (InteractType)i; + if (!typeString.empty()) interactArea.typeID = interact_type_id_get(typeString); interactAreas.emplace_back(std::move(interactArea)); } @@ -210,10 +220,10 @@ namespace game::resource::xml else logger.warning(std::format("No character cursor.xml file found: {}", path.string())); - if (auto playSchemaPath = physfs::Path(archive + "/" + "play.xml"); playSchemaPath.is_valid()) - playSchema = Play(playSchemaPath, dialogue); + if (auto skillCheckSchemaPath = physfs::Path(archive + "/" + "skill_check.xml"); skillCheckSchemaPath.is_valid()) + skillCheckSchema = SkillCheck(skillCheckSchemaPath, dialogue); else - logger.warning(std::format("No character play.xml file found: {}", path.string())); + logger.warning(std::format("No character skill_check.xml file found: {}", path.string())); logger.info(std::format("Initialized character: {}", name)); diff --git a/src/resource/xml/character.hpp b/src/resource/xml/character.hpp index 286e5bf..0ce5622 100644 --- a/src/resource/xml/character.hpp +++ b/src/resource/xml/character.hpp @@ -3,7 +3,6 @@ #include #include -#include "../../util/interact_type.hpp" #include "../audio.hpp" #include "animation_entry.hpp" #include "anm2.hpp" @@ -12,7 +11,7 @@ #include "dialogue.hpp" #include "item.hpp" #include "menu.hpp" -#include "play.hpp" +#include "skill_check.hpp" #include "save.hpp" namespace game::resource::xml @@ -51,7 +50,8 @@ namespace game::resource::xml int nullID{-1}; int layerID{-1}; - InteractType type{(InteractType)-1}; + int typeID{-1}; + bool isHold{}; Dialogue::PoolReference pool{-1}; float digestionBonusRub{}; @@ -97,7 +97,7 @@ namespace game::resource::xml Item itemSchema{}; Menu menuSchema{}; Cursor cursorSchema{}; - Play playSchema{}; + SkillCheck skillCheckSchema{}; Save save{}; @@ -107,9 +107,12 @@ namespace game::resource::xml Sounds sounds{}; + glm::vec3 color{0.120f, 0.515f, 0.115f}; + std::vector stages{}; std::vector expandAreas{}; std::vector eatAreas{}; + std::vector interactTypeNames{}; std::vector interactAreas{}; AlternateSpritesheet alternateSpritesheet{}; diff --git a/src/resource/xml/character_preview.cpp b/src/resource/xml/character_preview.cpp index 82f2c02..b3bd31e 100644 --- a/src/resource/xml/character_preview.cpp +++ b/src/resource/xml/character_preview.cpp @@ -42,6 +42,7 @@ namespace game::resource::xml query_string_attribute(root, "Name", &name); query_string_attribute(root, "Description", &description); query_string_attribute(root, "Author", &author); + query_vec3(root, "ColorR", "ColorG", "ColorB", color); root->QueryFloatAttribute("Weight", &weight); if (auto element = root->FirstChildElement("Stages")) diff --git a/src/resource/xml/character_preview.hpp b/src/resource/xml/character_preview.hpp index b3de36d..b201db0 100644 --- a/src/resource/xml/character_preview.hpp +++ b/src/resource/xml/character_preview.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -22,6 +23,7 @@ namespace game::resource::xml Texture portrait{}; Texture render{}; Save save{}; + glm::vec3 color{0.120f, 0.515f, 0.115f}; int stages{1}; diff --git a/src/resource/xml/item.cpp b/src/resource/xml/item.cpp index 51f393e..c43fa5d 100644 --- a/src/resource/xml/item.cpp +++ b/src/resource/xml/item.cpp @@ -142,7 +142,7 @@ namespace game::resource::xml query_int_optional_attribute(child, "UpgradeCount", item.upgradeCount); } - query_bool_attribute(child, "IsPlayReward", &item.isPlayReward); + query_bool_attribute(child, "IsSkillCheckReward", &item.isSkillCheckReward); query_bool_attribute(child, "IsToggleSpritesheet", &item.isToggleSpritesheet); std::string categoryString{}; @@ -173,7 +173,7 @@ namespace game::resource::xml { auto& item = items[i]; pools[item.rarityID].emplace_back(i); - if (item.isPlayReward) rewardItemPool.emplace_back(i); + if (item.isSkillCheckReward) skillCheckRewardItemPool.emplace_back(i); } for (int i = 0; i < (int)rarities.size(); i++) diff --git a/src/resource/xml/item.hpp b/src/resource/xml/item.hpp index a9168da..21bdc86 100644 --- a/src/resource/xml/item.hpp +++ b/src/resource/xml/item.hpp @@ -50,7 +50,7 @@ namespace game::resource::xml std::optional digestionBonus{}; std::optional gravity{}; std::optional chewCount{}; - bool isPlayReward{}; + bool isSkillCheckReward{}; bool isToggleSpritesheet{}; }; @@ -85,7 +85,7 @@ namespace game::resource::xml std::vector rarityIDsSortedByChance{}; std::unordered_map pools{}; - Pool rewardItemPool{}; + Pool skillCheckRewardItemPool{}; Animations animations{}; Sounds sounds{}; diff --git a/src/resource/xml/save.cpp b/src/resource/xml/save.cpp index f96aa71..22479b3 100644 --- a/src/resource/xml/save.cpp +++ b/src/resource/xml/save.cpp @@ -22,15 +22,13 @@ namespace game::resource::xml XMLDocument document; auto pathString = path.string(); - // Fail silently if there's no save. auto result = document.LoadFile(pathString.c_str()); if (result == XML_ERROR_FILE_NOT_FOUND || result == XML_ERROR_FILE_COULD_NOT_BE_OPENED) return; if (result != XML_SUCCESS) { - logger.error( - std::format("Could not initialize character save file: {} ({})", pathString, document.ErrorStr())); + logger.error(std::format("Could not initialize character save file: {} ({})", pathString, document.ErrorStr())); return; } @@ -54,7 +52,9 @@ namespace game::resource::xml element->QueryIntAttribute("TotalFoodItemsEaten", &totalFoodItemsEaten); } - if (auto element = root->FirstChildElement("Play")) + auto element = root->FirstChildElement("SkillCheck"); + if (!element) element = root->FirstChildElement("Play"); + if (element) { element->QueryIntAttribute("TotalPlays", &totalPlays); element->QueryIntAttribute("HighScore", &highScore); @@ -130,13 +130,13 @@ namespace game::resource::xml characterElement->SetAttribute("TotalCaloriesConsumed", totalCaloriesConsumed); characterElement->SetAttribute("TotalFoodItemsEaten", totalFoodItemsEaten); - auto playElement = element->InsertNewChildElement("Play"); + auto skillCheckElement = element->InsertNewChildElement("SkillCheck"); - playElement->SetAttribute("TotalPlays", totalPlays); - playElement->SetAttribute("HighScore", highScore); - playElement->SetAttribute("BestCombo", bestCombo); + skillCheckElement->SetAttribute("TotalPlays", totalPlays); + skillCheckElement->SetAttribute("HighScore", highScore); + skillCheckElement->SetAttribute("BestCombo", bestCombo); - auto gradesElement = playElement->InsertNewChildElement("Grades"); + auto gradesElement = skillCheckElement->InsertNewChildElement("Grades"); for (auto& [i, count] : gradeCounts) { diff --git a/src/resource/xml/settings.cpp b/src/resource/xml/settings.cpp index af78b57..559c66e 100644 --- a/src/resource/xml/settings.cpp +++ b/src/resource/xml/settings.cpp @@ -23,8 +23,7 @@ namespace game::resource::xml if (document.LoadFile(pathString.c_str()) != XML_SUCCESS) { - logger.error( - std::format("Could not initialize character save file: {} ({})", pathString, document.ErrorStr())); + logger.error(std::format("Could not initialize character save file: {} ({})", pathString, document.ErrorStr())); return; } @@ -34,13 +33,10 @@ namespace game::resource::xml query_string_attribute(root, "MeasurementSystem", &measurementSystemString); measurementSystem = measurementSystemString == "Imperial" ? measurement::IMPERIAL : measurement::METRIC; root->QueryIntAttribute("Volume", &volume); - root->QueryFloatAttribute("ColorR", &color.r); - root->QueryFloatAttribute("ColorG", &color.g); - root->QueryFloatAttribute("ColorB", &color.b); - root->QueryFloatAttribute("WindowX", &windowPosition.x); - root->QueryFloatAttribute("WindowY", &windowPosition.y); - root->QueryIntAttribute("WindowW", &windowSize.x); - root->QueryIntAttribute("WindowH", &windowSize.y); + query_vec3(root, "ColorR", "ColorG", "ColorB", color); + query_vec2(root, "WindowX", "WindowY", windowPosition); + query_ivec2(root, "WindowW", "WindowH", windowSize); + query_bool_attribute(root, "IsUseCharacterColor", &isUseCharacterColor); } logger.info(std::format("Initialized settings: {}", pathString)); @@ -59,13 +55,10 @@ namespace game::resource::xml element->SetAttribute("MeasurementSystem", measurementSystem == measurement::IMPERIAL ? "Imperial" : "Metric"); element->SetAttribute("Volume", volume); - element->SetAttribute("ColorR", color.r); - element->SetAttribute("ColorG", color.g); - element->SetAttribute("ColorB", color.b); - element->SetAttribute("WindowX", windowPosition.x); - element->SetAttribute("WindowY", windowPosition.y); - element->SetAttribute("WindowW", windowSize.x); - element->SetAttribute("WindowH", windowSize.y); + set_vec3_attribute(element, "ColorR", "ColorG", "ColorB", color); + set_vec2_attribute(element, "WindowX", "WindowY", windowPosition); + set_ivec2_attribute(element, "WindowW", "WindowH", windowSize); + set_bool_attribute(element, "IsUseCharacterColor", isUseCharacterColor); document.InsertFirstChild(element); diff --git a/src/resource/xml/settings.hpp b/src/resource/xml/settings.hpp index aa473a5..16c2b56 100644 --- a/src/resource/xml/settings.hpp +++ b/src/resource/xml/settings.hpp @@ -21,6 +21,7 @@ namespace game::resource::xml util::measurement::System measurementSystem{util::measurement::METRIC}; int volume{50}; + bool isUseCharacterColor{true}; glm::vec3 color{0.120f, 0.515f, 0.115f}; glm::ivec2 windowSize{1600, 900}; diff --git a/src/resource/xml/play.cpp b/src/resource/xml/skill_check.cpp similarity index 91% rename from src/resource/xml/play.cpp rename to src/resource/xml/skill_check.cpp index ada94ef..8fff4d5 100644 --- a/src/resource/xml/play.cpp +++ b/src/resource/xml/skill_check.cpp @@ -1,4 +1,4 @@ -#include "play.hpp" +#include "skill_check.hpp" #include "../../log.hpp" #include "util.hpp" @@ -10,7 +10,7 @@ using namespace game::util; namespace game::resource::xml { - Play::Play(const physfs::Path& path, Dialogue& dialogue) + SkillCheck::SkillCheck(const physfs::Path& path, Dialogue& dialogue) { XMLDocument document; @@ -62,8 +62,8 @@ namespace game::resource::xml } isValid = true; - logger.info(std::format("Initialized play schema: {}", path.c_str())); + logger.info(std::format("Initialized skill check schema: {}", path.c_str())); } - bool Play::is_valid() const { return isValid; }; + bool SkillCheck::is_valid() const { return isValid; }; } diff --git a/src/resource/xml/play.hpp b/src/resource/xml/skill_check.hpp similarity index 90% rename from src/resource/xml/play.hpp rename to src/resource/xml/skill_check.hpp index 537e229..70c3a91 100644 --- a/src/resource/xml/play.hpp +++ b/src/resource/xml/skill_check.hpp @@ -8,7 +8,7 @@ namespace game::resource::xml { - class Play + class SkillCheck { public: struct Grade @@ -48,8 +48,8 @@ namespace game::resource::xml bool isValid{}; - Play() = default; - Play(const util::physfs::Path&, Dialogue&); + SkillCheck() = default; + SkillCheck(const util::physfs::Path&, Dialogue&); bool is_valid() const; }; diff --git a/src/resource/xml/util.cpp b/src/resource/xml/util.cpp index 3f56643..ba23005 100644 --- a/src/resource/xml/util.cpp +++ b/src/resource/xml/util.cpp @@ -12,6 +12,8 @@ using namespace game::util; namespace game::resource::xml { + XMLError query_result_merge(XMLError result, XMLError next) { return result == XML_SUCCESS ? next : result; } + XMLError query_string_attribute(XMLElement* element, const char* attribute, std::string* value) { const char* temp = nullptr; @@ -45,6 +47,60 @@ namespace game::resource::xml return result; } + XMLError query_ivec2(XMLElement* element, const char* attributeX, const char* attributeY, glm::ivec2& value) + { + auto result = element->QueryIntAttribute(attributeX, &value.x); + result = query_result_merge(result, element->QueryIntAttribute(attributeY, &value.y)); + return result; + } + + XMLError query_vec2(XMLElement* element, const char* attributeX, const char* attributeY, glm::vec2& value) + { + auto result = element->QueryFloatAttribute(attributeX, &value.x); + result = query_result_merge(result, element->QueryFloatAttribute(attributeY, &value.y)); + return result; + } + + XMLError query_vec3(XMLElement* element, const char* attributeX, const char* attributeY, const char* attributeZ, + glm::vec3& value) + { + auto result = element->QueryFloatAttribute(attributeX, &value.x); + result = query_result_merge(result, element->QueryFloatAttribute(attributeY, &value.y)); + result = query_result_merge(result, element->QueryFloatAttribute(attributeZ, &value.z)); + return result; + } + + XMLError set_bool_attribute(XMLElement* element, const char* attribute, bool value) + { + element->SetAttribute(attribute, value ? "true" : "false"); + return XML_SUCCESS; + } + + XMLError set_ivec2_attribute(XMLElement* element, const char* attributeX, const char* attributeY, + const glm::ivec2& value) + { + element->SetAttribute(attributeX, value.x); + element->SetAttribute(attributeY, value.y); + return XML_SUCCESS; + } + + XMLError set_vec2_attribute(XMLElement* element, const char* attributeX, const char* attributeY, + const glm::vec2& value) + { + element->SetAttribute(attributeX, value.x); + element->SetAttribute(attributeY, value.y); + return XML_SUCCESS; + } + + XMLError set_vec3_attribute(XMLElement* element, const char* attributeX, const char* attributeY, + const char* attributeZ, const glm::vec3& value) + { + element->SetAttribute(attributeX, value.x); + element->SetAttribute(attributeY, value.y); + element->SetAttribute(attributeZ, value.z); + return XML_SUCCESS; + } + XMLError query_float_optional_attribute(XMLElement* element, const char* attribute, std::optional& value) { value.emplace(); @@ -84,102 +140,139 @@ namespace game::resource::xml return result; } - void query_event_id(XMLElement* element, const char* name, const Anm2& anm2, int& eventID) + XMLError query_event_id(XMLElement* element, const char* name, const Anm2& anm2, int& eventID) { std::string string{}; - query_string_attribute(element, name, &string); + auto result = query_string_attribute(element, name, &string); + if (result != XML_SUCCESS) return result; + if (anm2.eventMap.contains(string)) + { eventID = anm2.eventMap.at(string); + return XML_SUCCESS; + } else { logger.error(std::format("Could not query anm2 event ID: {} ({})", string, anm2.path)); eventID = -1; + return XML_ERROR_PARSING_ATTRIBUTE; } } - void query_layer_id(XMLElement* element, const char* name, const Anm2& anm2, int& layerID) + XMLError query_layer_id(XMLElement* element, const char* name, const Anm2& anm2, int& layerID) { std::string string{}; - query_string_attribute(element, name, &string); + auto result = query_string_attribute(element, name, &string); + if (result != XML_SUCCESS) return result; + if (anm2.layerMap.contains(string)) + { layerID = anm2.layerMap.at(string); + return XML_SUCCESS; + } else { logger.error(std::format("Could not query anm2 layer ID: {} ({})", string, anm2.path)); layerID = -1; + return XML_ERROR_PARSING_ATTRIBUTE; } } - void query_null_id(XMLElement* element, const char* name, const Anm2& anm2, int& nullID) + XMLError query_null_id(XMLElement* element, const char* name, const Anm2& anm2, int& nullID) { std::string string{}; - query_string_attribute(element, name, &string); + auto result = query_string_attribute(element, name, &string); + if (result != XML_SUCCESS) return result; + if (anm2.nullMap.contains(string)) + { nullID = anm2.nullMap.at(string); + return XML_SUCCESS; + } else { logger.error(std::format("Could not query anm2 null ID: {} ({})", string, anm2.path)); nullID = -1; + return XML_ERROR_PARSING_ATTRIBUTE; } } - void query_anm2(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath, - Anm2& anm2, Anm2::Flags flags) + XMLError query_anm2(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath, + Anm2& anm2, Anm2::Flags flags) { std::string string{}; - query_string_attribute(element, name, &string); + auto result = query_string_attribute(element, name, &string); + if (result != XML_SUCCESS) return result; + anm2 = Anm2(physfs::Path(archive + "/" + rootPath + "/" + string), flags); + return XML_SUCCESS; } - void query_texture(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath, - Texture& texture) + XMLError query_texture(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath, + Texture& texture) { std::string string{}; - query_string_attribute(element, name, &string); + auto result = query_string_attribute(element, name, &string); + if (result != XML_SUCCESS) return result; + texture = Texture(physfs::Path(archive + "/" + rootPath + "/" + string)); + return XML_SUCCESS; } - void query_sound(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath, - Audio& sound) + XMLError query_sound(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath, + Audio& sound) { std::string string{}; - query_string_attribute(element, name, &string); + auto result = query_string_attribute(element, name, &string); + if (result != XML_SUCCESS) return result; + sound = Audio(physfs::Path(archive + "/" + rootPath + "/" + string)); + return XML_SUCCESS; } - void query_font(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath, - Font& font) + XMLError query_font(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath, + Font& font) { std::string string{}; - query_string_attribute(element, name, &string); + auto result = query_string_attribute(element, name, &string); + if (result != XML_SUCCESS) return result; + font = Font(physfs::Path(archive + "/" + rootPath + "/" + string)); + return XML_SUCCESS; } - void query_animation_entry(XMLElement* element, AnimationEntry& animationEntry) + XMLError query_animation_entry(XMLElement* element, AnimationEntry& animationEntry) { - query_string_attribute(element, "Animation", &animationEntry.animation); - element->QueryFloatAttribute("Weight", &animationEntry.weight); + auto result = query_string_attribute(element, "Animation", &animationEntry.animation); + result = query_result_merge(result, element->QueryFloatAttribute("Weight", &animationEntry.weight)); + return result; } - void query_animation_entry_collection(XMLElement* element, const char* name, - AnimationEntryCollection& animationEntryCollection) + XMLError query_animation_entry_collection(XMLElement* element, const char* name, + AnimationEntryCollection& animationEntryCollection) { + auto result = XML_SUCCESS; for (auto child = element->FirstChildElement(name); child; child = child->NextSiblingElement(name)) - query_animation_entry(child, animationEntryCollection.emplace_back()); + result = query_result_merge(result, query_animation_entry(child, animationEntryCollection.emplace_back())); + return result; } - void query_sound_entry(XMLElement* element, const std::string& archive, const std::string& rootPath, - SoundEntry& soundEntry, const std::string& attributeName) + XMLError query_sound_entry(XMLElement* element, const std::string& archive, const std::string& rootPath, + SoundEntry& soundEntry, const std::string& attributeName) { - query_sound(element, attributeName.c_str(), archive, rootPath, soundEntry.sound); - element->QueryFloatAttribute("Weight", &soundEntry.weight); + auto result = query_sound(element, attributeName.c_str(), archive, rootPath, soundEntry.sound); + result = query_result_merge(result, element->QueryFloatAttribute("Weight", &soundEntry.weight)); + return result; } - void query_sound_entry_collection(XMLElement* element, const char* name, const std::string& archive, - const std::string& rootPath, SoundEntryCollection& soundEntryCollection, - const std::string& attributeName) + XMLError query_sound_entry_collection(XMLElement* element, const char* name, const std::string& archive, + const std::string& rootPath, SoundEntryCollection& soundEntryCollection, + const std::string& attributeName) { + auto result = XML_SUCCESS; for (auto child = element->FirstChildElement(name); child; child = child->NextSiblingElement(name)) - query_sound_entry(child, archive, rootPath, soundEntryCollection.emplace_back(), attributeName); + result = query_result_merge( + result, query_sound_entry(child, archive, rootPath, soundEntryCollection.emplace_back(), attributeName)); + return result; } } diff --git a/src/resource/xml/util.hpp b/src/resource/xml/util.hpp index 361ae07..b287958 100644 --- a/src/resource/xml/util.hpp +++ b/src/resource/xml/util.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include "animation_entry.hpp" @@ -19,33 +20,43 @@ namespace game::resource::xml tinyxml2::XMLError query_bool_attribute(tinyxml2::XMLElement*, const char*, bool*); tinyxml2::XMLError query_path_attribute(tinyxml2::XMLElement*, const char*, std::filesystem::path*); tinyxml2::XMLError query_color_attribute(tinyxml2::XMLElement*, const char*, float*); + tinyxml2::XMLError query_ivec2(tinyxml2::XMLElement*, const char*, const char*, glm::ivec2&); + tinyxml2::XMLError query_vec2(tinyxml2::XMLElement*, const char*, const char*, glm::vec2&); + tinyxml2::XMLError query_vec3(tinyxml2::XMLElement*, const char*, const char*, const char*, glm::vec3&); + tinyxml2::XMLError set_bool_attribute(tinyxml2::XMLElement*, const char*, bool); + tinyxml2::XMLError set_ivec2_attribute(tinyxml2::XMLElement*, const char*, const char*, const glm::ivec2&); + tinyxml2::XMLError set_vec2_attribute(tinyxml2::XMLElement*, const char*, const char*, const glm::vec2&); + tinyxml2::XMLError set_vec3_attribute(tinyxml2::XMLElement*, const char*, const char*, const char*, + const glm::vec3&); tinyxml2::XMLError query_float_optional_attribute(tinyxml2::XMLElement* element, const char* attribute, std::optional& value); tinyxml2::XMLError query_int_optional_attribute(tinyxml2::XMLElement* element, const char* attribute, std::optional& value); - void query_event_id(tinyxml2::XMLElement* element, const char* name, const Anm2& anm2, int& eventID); - void query_layer_id(tinyxml2::XMLElement* element, const char* name, const Anm2& anm2, int& layerID); - void query_null_id(tinyxml2::XMLElement* element, const char* name, const Anm2& anm2, int& nullID); + tinyxml2::XMLError query_event_id(tinyxml2::XMLElement* element, const char* name, const Anm2& anm2, int& eventID); + tinyxml2::XMLError query_layer_id(tinyxml2::XMLElement* element, const char* name, const Anm2& anm2, int& layerID); + tinyxml2::XMLError query_null_id(tinyxml2::XMLElement* element, const char* name, const Anm2& anm2, int& nullID); - void query_anm2(tinyxml2::XMLElement* element, const char* name, const std::string& archive, - const std::string& rootPath, Anm2& anm2, Anm2::Flags flags = {}); - void query_texture(tinyxml2::XMLElement* element, const char* name, const std::string& archive, - const std::string& rootPath, Texture& texture); - void query_sound(tinyxml2::XMLElement* element, const char* name, const std::string& archive, - const std::string& rootPath, Audio& sound); - void query_font(tinyxml2::XMLElement* element, const char* name, const std::string& archive, - const std::string& rootPath, Font& font); + tinyxml2::XMLError query_anm2(tinyxml2::XMLElement* element, const char* name, const std::string& archive, + const std::string& rootPath, Anm2& anm2, Anm2::Flags flags = {}); + tinyxml2::XMLError query_texture(tinyxml2::XMLElement* element, const char* name, const std::string& archive, + const std::string& rootPath, Texture& texture); + tinyxml2::XMLError query_sound(tinyxml2::XMLElement* element, const char* name, const std::string& archive, + const std::string& rootPath, Audio& sound); + tinyxml2::XMLError query_font(tinyxml2::XMLElement* element, const char* name, const std::string& archive, + const std::string& rootPath, Font& font); - void query_animation_entry(tinyxml2::XMLElement* element, AnimationEntry& animationEntry); - void query_animation_entry_collection(tinyxml2::XMLElement* element, const char* name, - AnimationEntryCollection& animationEntryCollection); + tinyxml2::XMLError query_animation_entry(tinyxml2::XMLElement* element, AnimationEntry& animationEntry); + tinyxml2::XMLError query_animation_entry_collection(tinyxml2::XMLElement* element, const char* name, + AnimationEntryCollection& animationEntryCollection); - void query_sound_entry(tinyxml2::XMLElement* element, const std::string& archive, const std::string& rootPath, - SoundEntry& soundEntry, const std::string& attributeName = "Sound"); - void query_sound_entry_collection(tinyxml2::XMLElement* element, const char* name, const std::string& archive, - const std::string& rootPath, SoundEntryCollection& soundEntryCollection, - const std::string& attributeName = "Sound"); + tinyxml2::XMLError query_sound_entry(tinyxml2::XMLElement* element, const std::string& archive, + const std::string& rootPath, SoundEntry& soundEntry, + const std::string& attributeName = "Sound"); + tinyxml2::XMLError query_sound_entry_collection(tinyxml2::XMLElement* element, const char* name, + const std::string& archive, const std::string& rootPath, + SoundEntryCollection& soundEntryCollection, + const std::string& attributeName = "Sound"); tinyxml2::XMLError document_load(const util::physfs::Path&, tinyxml2::XMLDocument&); } diff --git a/src/state.cpp b/src/state.cpp index 07cf37d..9bcd7f5 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -31,8 +31,8 @@ namespace game case SELECT: select.tick(); break; - case MAIN: - main.tick(resources); + case PLAY: + play.tick(resources); break; default: break; @@ -52,7 +52,7 @@ namespace game ImGui_ImplSDL3_ProcessEvent(&event); if (event.type == SDL_EVENT_QUIT) { - if (type == MAIN) main.exit(resources); + if (type == PLAY) play.exit(resources); isRunning = false; } if (!isRunning) return; @@ -68,30 +68,30 @@ namespace game select.update(resources); if (select.info.isNewGame || select.info.isContinue) { - Main::Game game = select.info.isNewGame ? Main::NEW_GAME : Main::CONTINUE; - if (game == Main::NEW_GAME) resources.character_save_set(select.characterIndex, resource::xml::Save()); + Play::Game game = select.info.isNewGame ? Play::NEW_GAME : Play::CONTINUE; + if (game == Play::NEW_GAME) resources.character_save_set(select.characterIndex, resource::xml::Save()); - main.set(resources, select.characterIndex, game); - type = MAIN; + play.set(resources, select.characterIndex, game); + type = PLAY; select.info.isNewGame = false; select.info.isContinue = false; } break; - case MAIN: - main.update(resources); - if (main.menu.configuration.isGoToSelect) + case PLAY: + play.update(resources); + if (play.menu.settingsMenu.isGoToSelect) { - main.exit(resources); + play.exit(resources); type = SELECT; - main.menu.configuration.isGoToSelect = false; + play.menu.settingsMenu.isGoToSelect = false; } break; default: break; } - auto isHideCursor = type == MAIN; + auto isHideCursor = type == PLAY; if (isHideCursor != isCursorHidden) { if (isHideCursor) @@ -104,6 +104,8 @@ namespace game void State::render() { + auto& color = + resources.settings.isUseCharacterColor && type == PLAY ? play.character.data.color : resources.settings.color; auto windowSize = resources.settings.windowSize; #ifndef __EMSCRIPTEN__ SDL_GetWindowSize(window, &windowSize.x, &windowSize.y); @@ -111,7 +113,7 @@ namespace game canvas.bind(); canvas.size_set(windowSize); - canvas.clear(vec4(resources.settings.color, 1.0f)); + canvas.clear(vec4(color, 1.0f)); canvas.unbind(); switch (type) @@ -119,8 +121,8 @@ namespace game case SELECT: select.render(resources, canvas); break; - case MAIN: - main.render(resources, canvas); + case PLAY: + play.render(resources, canvas); break; default: break; diff --git a/src/state.hpp b/src/state.hpp index e01400a..4d639d7 100644 --- a/src/state.hpp +++ b/src/state.hpp @@ -2,10 +2,10 @@ #include -#include "canvas.hpp" +#include "render/canvas.hpp" #include "resources.hpp" -#include "state/main.hpp" +#include "state/play.hpp" #include "state/select.hpp" #include "entity/cursor.hpp" @@ -22,7 +22,7 @@ namespace game enum Type { - MAIN, + PLAY, SELECT }; @@ -30,7 +30,7 @@ namespace game Resources resources; - state::Main main; + state::Play play; state::Select select; void tick(); diff --git a/src/state/main/inventory.cpp b/src/state/main/inventory.cpp deleted file mode 100644 index 35189b3..0000000 --- a/src/state/main/inventory.cpp +++ /dev/null @@ -1,228 +0,0 @@ -#include "inventory.hpp" - -#include -#include -#include - -#include "../../util/color.hpp" -#include "../../util/imgui.hpp" -#include "../../util/imgui/widget.hpp" -#include "../../util/math.hpp" - -using namespace game::util; -using namespace game::util::imgui; -using namespace game::entity; -using namespace game::resource; -using namespace glm; - -namespace game::state::main -{ - void Inventory::tick() - { - for (auto& [i, actor] : actors) - actor.tick(); - } - - void Inventory::update(Resources& resources, ItemManager& itemManager, entity::Character& character) - { - auto& schema = character.data.itemSchema; - - if (!itemManager.returnItemIDs.empty()) - { - for (auto& id : itemManager.returnItemIDs) - values[id]++; - itemManager.returnItemIDs.clear(); - } - - if (ImGui::BeginChild("##Inventory Child")) - { - auto cursorPos = ImGui::GetCursorPos(); - auto cursorStartX = ImGui::GetCursorPosX(); - - auto size = ImVec2(SIZE, SIZE); - - for (int i = 0; i < (int)schema.items.size(); i++) - { - auto& item = schema.items[i]; - auto& quantity = values[i]; - auto& category = schema.categories[item.categoryID]; - auto& calories = item.calories; - auto& digestionBonus = item.digestionBonus; - auto& eatSpeedBonus = item.eatSpeedBonus; - auto& rarity = schema.rarities[item.rarityID]; - - quantity = glm::clamp(0, quantity, schema.quantityMax); - if (rarity.isHidden && quantity <= 0) continue; - - ImGui::PushID(i); - - ImGui::SetCursorPos(cursorPos); - auto cursorScreenPos = ImGui::GetCursorScreenPos(); - - if (!actors.contains(i)) - { - actors[i] = Actor(schema.anm2s[i], {}, Actor::SET); - rects[i] = actors[i].rect(); - } - auto& rect = rects[i]; - auto rectSize = vec2(rect.z, rect.w); - - auto previewScale = (size.x <= 0.0f || size.y <= 0.0f || rectSize.x <= 0.0f || rectSize.y <= 0.0f || - !std::isfinite(rectSize.x) || !std::isfinite(rectSize.y)) - ? 0.0f - : std::min(size.x / rectSize.x, size.y / rectSize.y); - - auto previewSize = rectSize * previewScale; - auto canvasSize = ivec2(std::max(1.0f, previewSize.x), std::max(1.0f, previewSize.y)); - if (!canvases.contains(i)) canvases.emplace((int)i, Canvas(canvasSize, Canvas::FLIP)); - auto& canvas = canvases[i]; - bool isPossibleToUpgrade = item.upgradeID.has_value() && item.upgradeCount.has_value() && - schema.idToStringMap.contains(*item.upgradeID); - bool isAbleToUpgrade = isPossibleToUpgrade && quantity >= *item.upgradeCount; - canvas.zoom = math::to_percent(previewScale); - canvas.pan = vec2(rect.x, rect.y); - canvas.bind(); - canvas.size_set(canvasSize); - canvas.clear(); - - actors[i].render(resources.shaders[shader::TEXTURE], resources.shaders[shader::RECT], canvas); - canvas.unbind(); - - ImGui::BeginDisabled(quantity < 1); - if (WIDGET_FX(ImGui::ImageButton("##Image Button", canvas.texture, size, ImVec2(), ImVec2(1, 1), ImVec4(), - quantity <= 0 ? ImVec4(0, 0, 0, 1) : ImVec4(1, 1, 1, 1))) && - quantity > 0) - { - if (ImGui::IsKeyDown(ImGuiMod_Shift)) - { - if (isAbleToUpgrade) - { - if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) - { - while (quantity >= *item.upgradeCount) - { - values.at(*item.upgradeID)++; - quantity -= *item.upgradeCount; - } - } - else - { - values.at(*item.upgradeID)++; - quantity -= *item.upgradeCount; - } - - schema.sounds.upgrade.play(); - } - else - schema.sounds.upgradeFail.play(); - } - else if (category.isEdible) - { - if (itemManager.items.size() + 1 >= ItemManager::LIMIT) - character.data.itemSchema.sounds.dispose.play(); - else - { - character.data.itemSchema.sounds.summon.play(); - itemManager.queuedItemIDs.emplace_back(i); - quantity--; - } - } - else if (item.isToggleSpritesheet) - { - character.spritesheet_set(character.spritesheetType == Character::NORMAL ? Character::ALTERNATE - : Character::NORMAL); - character.data.alternateSpritesheet.sound.play(); - quantity--; - } - } - - ImGui::EndDisabled(); - - if (ImGui::BeginItemTooltip()) - { - if (quantity > 0) - { - ImGui::PushFont(ImGui::GetFont(), Font::BIG); - - ImGui::Text("%s (x%i)", item.name.c_str(), quantity); - - ImGui::Separator(); - - ImGui::PopFont(); - - ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(imgui::to_imvec4(color::GRAY))); - - ImGui::Text("-- %s (%s) --", category.name.c_str(), rarity.name.c_str()); - if (item.flavorID.has_value()) ImGui::Text("Flavor: %s", schema.flavors[*item.flavorID].name.c_str()); - if (calories.has_value()) ImGui::Text("%0.0f kcal", *calories); - if (digestionBonus.has_value()) - { - if (*digestionBonus > 0) - ImGui::Text("Digestion Rate Bonus: +%0.2f%% / sec", *digestionBonus * 60.0f); - else if (digestionBonus < 0) - ImGui::Text("Digestion Rate Penalty: %0.2f%% / sec", *digestionBonus * 60.0f); - } - if (eatSpeedBonus.has_value()) - { - if (*eatSpeedBonus > 0) - ImGui::Text("Eat Speed Bonus: +%0.2f%% / sec", *eatSpeedBonus); - else if (eatSpeedBonus < 0) - ImGui::Text("Eat Speed Penalty: %0.2f%% / sec", *eatSpeedBonus); - } - - if (isPossibleToUpgrade) - { - ImGui::Text("Upgrade: %ix -> %s", *item.upgradeCount, schema.idToStringMap.at(*item.upgradeID).c_str()); - if (isAbleToUpgrade) - ImGui::TextUnformatted("(Shift + Click -> Upgrade)\n(Shift + Ctrl + Click -> Upgrade All)"); - } - - ImGui::PopStyleColor(); - - ImGui::Separator(); - ImGui::TextUnformatted(item.description.c_str()); - } - else - { - ImGui::PushFont(ImGui::GetFont(), Font::BIG); - ImGui::TextUnformatted("???"); - ImGui::PopFont(); - } - - ImGui::EndTooltip(); - } - - ImGui::PushFont(ImGui::GetFont(), Font::BIG); - - auto text = std::format("x{}", quantity); - auto textPos = ImVec2(cursorScreenPos.x + size.x - ImGui::CalcTextSize(text.c_str()).x, - cursorScreenPos.y + size.y - ImGui::GetTextLineHeightWithSpacing()); - ImGui::GetWindowDrawList()->AddText(textPos, ImGui::GetColorU32(ImGui::GetStyleColorVec4(ImGuiCol_Text)), - text.c_str()); - ImGui::PopFont(); - - auto increment = ImGui::GetItemRectSize().x + ImGui::GetStyle().ItemSpacing.x; - cursorPos.x += increment; - - if (cursorPos.x + increment > ImGui::GetContentRegionAvail().x) - { - cursorPos.x = cursorStartX; - cursorPos.y += increment; - } - - ImGui::PopID(); - } - - if (count() == 0) ImGui::Text("Check the \"Play\" tab to earn rewards!"); - } - ImGui::EndChild(); - } - - int Inventory::count() - { - int count{}; - for (auto& [type, quantity] : values) - count += quantity; - return count; - } -} diff --git a/src/state/main.cpp b/src/state/play.cpp similarity index 81% rename from src/state/main.cpp rename to src/state/play.cpp index 3ad2b40..8bff6ed 100644 --- a/src/state/main.cpp +++ b/src/state/play.cpp @@ -1,4 +1,4 @@ -#include "main.hpp" +#include "play.hpp" #include #include @@ -12,12 +12,12 @@ using namespace game::resource; using namespace game::util; -using namespace game::state::main; +using namespace game::state::play; using namespace glm; namespace game::state { - World::Focus Main::focus_get() + World::Focus Play::focus_get() { if (!isWindows) return World::CENTER; @@ -27,7 +27,7 @@ namespace game::state : World::CENTER; } - void Main::set(Resources& resources, int selectedCharacterIndex, enum Game game) + void Play::set(Resources& resources, int selectedCharacterIndex, enum Game game) { auto& data = resources.character_get(selectedCharacterIndex); auto& saveData = data.save; @@ -35,8 +35,8 @@ namespace game::state auto& dialogue = data.dialogue; auto& menuSchema = data.menuSchema; this->characterIndex = selectedCharacterIndex; - konamiCodeIndex = 0; - konamiCodeStartTime = 0.0; + cheatCodeIndex = 0; + cheatCodeStartTime = 0.0; character = entity::Character(data, vec2(World::BOUNDS.x + World::BOUNDS.z * 0.5f, World::BOUNDS.w - World::BOUNDS.y)); @@ -58,6 +58,7 @@ namespace game::state characterManager = CharacterManager{}; cursor = entity::Cursor(character.data.cursorSchema.anm2); + cursor.interactTypeID = character.data.interactTypeNames.empty() ? -1 : 0; menu.inventory = Inventory{}; for (auto& [id, quantity] : saveData.inventory) @@ -79,14 +80,14 @@ namespace game::state imgui::style::rounding_set(menuSchema.rounding); imgui::widget::sounds_set(&menuSchema.sounds.hover, &menuSchema.sounds.select); + menu.color_set_check(resources, character); - menu.play = Play(character); - menu.play.totalPlays = saveData.totalPlays; - menu.play.highScore = saveData.highScore; - menu.play.bestCombo = saveData.bestCombo; - menu.play.gradeCounts = saveData.gradeCounts; - menu.play.isHighScoreAchieved = saveData.highScore > 0 ? true : false; - + menu.skillCheck = SkillCheck(character); + menu.skillCheck.totalPlays = saveData.totalPlays; + menu.skillCheck.highScore = saveData.highScore; + menu.skillCheck.bestCombo = saveData.bestCombo; + menu.skillCheck.gradeCounts = saveData.gradeCounts; + menu.skillCheck.isHighScoreAchieved = saveData.highScore > 0 ? true : false; menu.isChat = character.data.dialogue.help.is_valid() || character.data.dialogue.random.is_valid(); text.entry = nullptr; @@ -114,17 +115,31 @@ namespace game::state isStartBegin = false; isStartEnd = false; } + + if (isPostgame) + { + isEnd = true; + isEndBegin = true; + isEndEnd = true; + } + else + { + isEnd = false; + isEndBegin = false; + isEndEnd = false; + } } - void Main::exit(Resources& resources) + void Play::exit(Resources& resources) { + imgui::style::color_set(resources.settings.color); imgui::style::rounding_set(); imgui::widget::sounds_set(nullptr, nullptr); ImGui::GetIO().FontDefault = resources.font.get(); save(resources); } - void Main::tick(Resources&) + void Play::tick(Resources&) { character.tick(); cursor.tick(); @@ -136,54 +151,54 @@ namespace game::state item.tick(); } - void Main::update(Resources& resources) + void Play::update(Resources& resources) { - static constexpr std::array KONAMI_CODE = { + static constexpr std::array CHEAT_CODE = { ImGuiKey_UpArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow, ImGuiKey_DownArrow, ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_B, ImGuiKey_A}; - static constexpr std::array KONAMI_INPUT_KEYS = { + static constexpr std::array CHEAT_INPUT_KEYS = { ImGuiKey_UpArrow, ImGuiKey_DownArrow, ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_B, ImGuiKey_A}; - static constexpr auto KONAMI_CODE_INPUT_TIME_SECONDS = 5.0; + static constexpr auto CHEAT_CODE_INPUT_TIME_SECONDS = 5.0; auto focus = focus_get(); auto& dialogue = character.data.dialogue; if (!menu.isCheats) { - for (auto key : KONAMI_INPUT_KEYS) + for (auto key : CHEAT_INPUT_KEYS) { if (!ImGui::IsKeyPressed(key, false)) continue; - if (key == KONAMI_CODE[konamiCodeIndex]) + if (key == CHEAT_CODE[cheatCodeIndex]) { - konamiCodeIndex++; - konamiCodeStartTime = ImGui::GetTime(); + cheatCodeIndex++; + cheatCodeStartTime = ImGui::GetTime(); } - else if (key == KONAMI_CODE[0]) + else if (key == CHEAT_CODE[0]) { - konamiCodeIndex = 1; - konamiCodeStartTime = ImGui::GetTime(); + cheatCodeIndex = 1; + cheatCodeStartTime = ImGui::GetTime(); } else { - konamiCodeIndex = 0; - konamiCodeStartTime = 0.0; + cheatCodeIndex = 0; + cheatCodeStartTime = 0.0; } - if (konamiCodeIndex >= (int)KONAMI_CODE.size()) + if (cheatCodeIndex >= (int)CHEAT_CODE.size()) { menu.isCheats = true; - konamiCodeIndex = 0; - konamiCodeStartTime = 0.0; + cheatCodeIndex = 0; + cheatCodeStartTime = 0.0; toasts.push("Cheats unlocked!"); character.data.menuSchema.sounds.cheatsActivated.play(); } } - if (konamiCodeIndex > 0 && (ImGui::GetTime() - konamiCodeStartTime > KONAMI_CODE_INPUT_TIME_SECONDS)) + if (cheatCodeIndex > 0 && (ImGui::GetTime() - cheatCodeStartTime > CHEAT_CODE_INPUT_TIME_SECONDS)) { - konamiCodeIndex = 0; - konamiCodeStartTime = 0.0; + cheatCodeIndex = 0; + cheatCodeStartTime = 0.0; } } @@ -264,15 +279,15 @@ namespace game::state cursor.update(); world.update(character, cursor, worldCanvas, focus); - if (autosaveTime += ImGui::GetIO().DeltaTime; autosaveTime > AUTOSAVE_TIME || menu.configuration.isSave) + if (autosaveTime += ImGui::GetIO().DeltaTime; autosaveTime > AUTOSAVE_TIME || menu.settingsMenu.isSave) { save(resources); autosaveTime = 0; - menu.configuration.isSave = false; + menu.settingsMenu.isSave = false; } } - void Main::render(Resources& resources, Canvas& canvas) + void Play::render(Resources& resources, Canvas& canvas) { auto& textureShader = resources.shaders[shader::TEXTURE]; auto& rectShader = resources.shaders[shader::RECT]; @@ -309,7 +324,7 @@ namespace game::state canvas.unbind(); } - void Main::save(Resources& resources) + void Play::save(Resources& resources) { resource::xml::Save save; @@ -323,10 +338,10 @@ namespace game::state save.digestionTimer = character.digestionTimer; save.totalCaloriesConsumed = character.totalCaloriesConsumed; save.totalFoodItemsEaten = character.totalFoodItemsEaten; - save.totalPlays = menu.play.totalPlays; - save.highScore = menu.play.highScore; - save.bestCombo = menu.play.bestCombo; - save.gradeCounts = menu.play.gradeCounts; + save.totalPlays = menu.skillCheck.totalPlays; + save.highScore = menu.skillCheck.highScore; + save.bestCombo = menu.skillCheck.bestCombo; + save.gradeCounts = menu.skillCheck.gradeCounts; save.isPostgame = isPostgame; save.isAlternateSpritesheet = character.spritesheetType == entity::Character::ALTERNATE; diff --git a/src/state/main.hpp b/src/state/play.hpp similarity index 51% rename from src/state/main.hpp rename to src/state/play.hpp index cadf6ef..65fe283 100644 --- a/src/state/main.hpp +++ b/src/state/play.hpp @@ -2,19 +2,19 @@ #include "../resources.hpp" -#include "main/area_manager.hpp" -#include "main/character_manager.hpp" -#include "main/info.hpp" -#include "main/item_manager.hpp" -#include "main/menu.hpp" -#include "main/text.hpp" -#include "main/toasts.hpp" -#include "main/tools.hpp" -#include "main/world.hpp" +#include "play/area_manager.hpp" +#include "play/character_manager.hpp" +#include "play/info.hpp" +#include "play/item_manager.hpp" +#include "play/menu.hpp" +#include "play/text.hpp" +#include "play/toasts.hpp" +#include "play/tools.hpp" +#include "play/world.hpp" namespace game::state { - class Main + class Play { public: static constexpr auto AUTOSAVE_TIME = 30.0f; @@ -28,22 +28,22 @@ namespace game::state entity::Character character; entity::Cursor cursor; - main::Info info; - main::Menu menu; - main::Tools tools; - main::Text text; - main::World world; - main::Toasts toasts; - main::ItemManager itemManager{}; - main::CharacterManager characterManager{}; - main::AreaManager areaManager{}; + play::Info info; + play::Menu menu; + play::Tools tools; + play::Text text; + play::World world; + play::Toasts toasts; + play::ItemManager itemManager{}; + play::CharacterManager characterManager{}; + play::AreaManager areaManager{}; int characterIndex{}; int areaIndex{}; float autosaveTime{}; - int konamiCodeIndex{}; - double konamiCodeStartTime{}; + int cheatCodeIndex{}; + double cheatCodeStartTime{}; bool isWindows{true}; @@ -57,15 +57,15 @@ namespace game::state bool isPostgame{}; - Canvas worldCanvas{main::World::SIZE}; + Canvas worldCanvas{play::World::SIZE}; - Main() = default; + Play() = default; void set(Resources&, int characterIndex, Game = CONTINUE); void exit(Resources& resources); void update(Resources&); void tick(Resources&); void render(Resources&, Canvas&); void save(Resources&); - main::World::Focus focus_get(); + play::World::Focus focus_get(); }; }; diff --git a/src/state/main/play.cpp b/src/state/play/arcade/skill_check.cpp similarity index 94% rename from src/state/main/play.cpp rename to src/state/play/arcade/skill_check.cpp index e99936d..9caeedd 100644 --- a/src/state/main/play.cpp +++ b/src/state/play/arcade/skill_check.cpp @@ -1,10 +1,10 @@ -#include "play.hpp" +#include "skill_check.hpp" #include -#include "../../util/imgui.hpp" -#include "../../util/imgui/widget.hpp" -#include "../../util/math.hpp" +#include "../../../util/imgui.hpp" +#include "../../../util/imgui/widget.hpp" +#include "../../../util/math.hpp" #include #include @@ -15,13 +15,13 @@ using namespace game::entity; using namespace game::resource; using namespace glm; -namespace game::state::main +namespace game::state::play { - float Play::accuracy_score_get(entity::Character& character) + float SkillCheck::accuracy_score_get(entity::Character& character) { if (totalPlays == 0) return 0.0f; - auto& schema = character.data.playSchema; + auto& schema = character.data.skillCheckSchema; float combinedWeight{}; @@ -34,9 +34,9 @@ namespace game::state::main return glm::clamp(0.0f, math::to_percent(combinedWeight / totalPlays), 100.0f); } - Play::Challenge Play::challenge_generate(entity::Character& character) + SkillCheck::Challenge SkillCheck::challenge_generate(entity::Character& character) { - auto& schema = character.data.playSchema; + auto& schema = character.data.skillCheckSchema; Challenge newChallenge; @@ -61,15 +61,15 @@ namespace game::state::main return newChallenge; } - Play::Play(entity::Character& character) { challenge = challenge_generate(character); } + SkillCheck::SkillCheck(entity::Character& character) { challenge = challenge_generate(character); } - void Play::tick() + void SkillCheck::tick() { for (auto& [i, actor] : itemActors) actor.tick(); } - void Play::update(Resources& resources, entity::Character& character, Inventory& inventory, Text& text) + void SkillCheck::update(Resources& resources, entity::Character& character, Inventory& inventory, Text& text) { static constexpr auto BG_COLOR_MULTIPLIER = 0.5f; static constexpr ImVec4 LINE_COLOR = ImVec4(1, 1, 1, 1); @@ -80,7 +80,7 @@ namespace game::state::main static constexpr auto ITEM_FALL_GRAVITY = 2400.0f; auto& dialogue = character.data.dialogue; - auto& schema = character.data.playSchema; + auto& schema = character.data.skillCheckSchema; auto& itemSchema = character.data.itemSchema; auto& style = ImGui::GetStyle(); auto drawList = ImGui::GetWindowDrawList(); @@ -202,7 +202,7 @@ namespace game::state::main auto barButtonSize = ImVec2(barMax.x - barMin.x, barMax.y - barMin.y); if (ImGui::IsKeyPressed(ImGuiKey_Space) || - WIDGET_FX(ImGui::InvisibleButton("##PlayBar", barButtonSize, ImGuiButtonFlags_PressedOnClick))) + WIDGET_FX(ImGui::InvisibleButton("##SkillCheckBar", barButtonSize, ImGuiButtonFlags_PressedOnClick))) { int gradeID{}; @@ -234,7 +234,7 @@ namespace game::state::main schema.sounds.rewardScore.play(); isRewardScoreAchieved = true; - for (auto& itemID : itemSchema.rewardItemPool) + for (auto& itemID : itemSchema.skillCheckRewardItemPool) { inventory.values[itemID]++; if (!itemActors.contains(itemID)) diff --git a/src/state/main/play.hpp b/src/state/play/arcade/skill_check.hpp similarity index 81% rename from src/state/main/play.hpp rename to src/state/play/arcade/skill_check.hpp index 46ffbad..f64b42f 100644 --- a/src/state/main/play.hpp +++ b/src/state/play/arcade/skill_check.hpp @@ -1,21 +1,21 @@ #pragma once -#include "../../canvas.hpp" -#include "../../entity/actor.hpp" -#include "../../entity/character.hpp" -#include "../../resources.hpp" +#include "../../../render/canvas.hpp" +#include "../../../entity/actor.hpp" +#include "../../../entity/character.hpp" +#include "../../../resources.hpp" -#include "inventory.hpp" -#include "text.hpp" +#include "../inventory.hpp" +#include "../text.hpp" #include #include #include #include -namespace game::state::main +namespace game::state::play { - class Play + class SkillCheck { public: @@ -77,8 +77,8 @@ namespace game::state::main std::unordered_map itemRects{}; std::unordered_map itemCanvases{}; - Play() = default; - Play(entity::Character&); + SkillCheck() = default; + SkillCheck(entity::Character&); Challenge challenge_generate(entity::Character&); void tick(); void update(Resources&, entity::Character&, Inventory&, Text&); diff --git a/src/state/main/area_manager.cpp b/src/state/play/area_manager.cpp similarity index 94% rename from src/state/main/area_manager.cpp rename to src/state/play/area_manager.cpp index d177f66..572b2da 100644 --- a/src/state/main/area_manager.cpp +++ b/src/state/play/area_manager.cpp @@ -5,7 +5,7 @@ using namespace game::resource; using namespace game::util; -namespace game::state::main +namespace game::state::play { int AreaManager::get(entity::Character& character) { diff --git a/src/state/main/area_manager.hpp b/src/state/play/area_manager.hpp similarity index 82% rename from src/state/main/area_manager.hpp rename to src/state/play/area_manager.hpp index 1c2757a..4f12b4a 100644 --- a/src/state/main/area_manager.hpp +++ b/src/state/play/area_manager.hpp @@ -2,7 +2,7 @@ #include "../../entity/character.hpp" -namespace game::state::main +namespace game::state::play { class AreaManager { diff --git a/src/state/main/character_manager.cpp b/src/state/play/character_manager.cpp similarity index 86% rename from src/state/main/character_manager.cpp rename to src/state/play/character_manager.cpp index 128b273..b6adec5 100644 --- a/src/state/main/character_manager.cpp +++ b/src/state/play/character_manager.cpp @@ -8,7 +8,7 @@ using namespace game::resource::xml; using namespace game::util; -namespace game::state::main +namespace game::state::play { void CharacterManager::update(entity::Character& character, entity::Cursor& cursor, Text& text, Canvas& canvas) { @@ -36,12 +36,19 @@ namespace game::state::main isInteractingPrevious = isInteracting; isHoveringPrevious = isHovering; + isHoldInteractingPrevious = isHoldInteracting; isHovering = false; + if (!isInteracting) isHoldInteracting = false; - if (isJustStoppedInteracting) + if (isJustStoppedHoldInteracting) + { + cursor.queue_play({cursor.defaultAnimation}); + if (character.queuedPlay.empty()) character.queue_idle_animation(); + isJustStoppedHoldInteracting = false; + } + else if (isJustStoppedInteracting) { cursor.queue_play({cursor.defaultAnimation}); - if (cursor.mode == RUB && character.queuedPlay.empty()) character.queue_idle_animation(); isJustStoppedInteracting = false; } @@ -58,7 +65,7 @@ namespace game::state::main auto rect = character.null_frame_rect(interactArea.nullID); if (cursor.state == entity::Cursor::DEFAULT && math::is_point_in_rectf(rect, cursorWorldPosition) && - !isImguiCaptureMouse && interactArea.type == cursor.mode) + !isImguiCaptureMouse && interactArea.typeID == cursor.interactTypeID) { cursor.state = entity::Cursor::HOVER; cursor.queue_play({interactArea.animationCursorHover}); @@ -68,8 +75,8 @@ namespace game::state::main if (isMouseLeftClick) { isInteracting = true; + isHoldInteracting = interactArea.isHold; interactArea.sound.play(); - lastInteractType = cursor.mode; if (interactArea.digestionBonusClick > 0 && character.calories > 0 && !character.isDigesting) character.digestionProgress += interactArea.digestionBonusClick; @@ -105,11 +112,13 @@ namespace game::state::main isImguiCaptureMouse) { isInteracting = false; + isHoldInteracting = false; interactAreaID = -1; } } if (isInteracting != isInteractingPrevious && !isInteracting) isJustStoppedInteracting = true; + if (isHoldInteracting != isHoldInteractingPrevious && !isHoldInteracting) isJustStoppedHoldInteracting = true; if (isHovering != isHoveringPrevious && !isHovering) isJustStoppedHovering = true; cursorWorldPositionPrevious = cursorWorldPosition; diff --git a/src/state/main/character_manager.hpp b/src/state/play/character_manager.hpp similarity index 79% rename from src/state/main/character_manager.hpp rename to src/state/play/character_manager.hpp index 8818d08..479165f 100644 --- a/src/state/main/character_manager.hpp +++ b/src/state/play/character_manager.hpp @@ -4,7 +4,7 @@ #include "../../entity/cursor.hpp" #include "text.hpp" -namespace game::state::main +namespace game::state::play { class CharacterManager { @@ -15,8 +15,10 @@ namespace game::state::main bool isHoveringPrevious{}; bool isJustStoppedInteracting{}; bool isJustStoppedHovering{}; + bool isHoldInteracting{}; + bool isHoldInteractingPrevious{}; + bool isJustStoppedHoldInteracting{}; int interactAreaID{-1}; - InteractType lastInteractType{(InteractType)-1}; glm::vec2 cursorWorldPositionPrevious{}; std::string queuedAnimation{}; diff --git a/src/state/main/chat.cpp b/src/state/play/chat.cpp similarity index 97% rename from src/state/main/chat.cpp rename to src/state/play/chat.cpp index f5064a1..6244500 100644 --- a/src/state/main/chat.cpp +++ b/src/state/play/chat.cpp @@ -5,7 +5,7 @@ using namespace game::resource; using namespace game::util::imgui; -namespace game::state::main +namespace game::state::play { void Chat::update(Resources&, Text& text, entity::Character& character) { diff --git a/src/state/main/chat.hpp b/src/state/play/chat.hpp similarity index 84% rename from src/state/main/chat.hpp rename to src/state/play/chat.hpp index bf3ff2f..78b7803 100644 --- a/src/state/main/chat.hpp +++ b/src/state/play/chat.hpp @@ -4,7 +4,7 @@ #include -namespace game::state::main +namespace game::state::play { class Chat { diff --git a/src/state/main/cheats.cpp b/src/state/play/cheats.cpp similarity index 99% rename from src/state/main/cheats.cpp rename to src/state/play/cheats.cpp index 597b81a..a867854 100644 --- a/src/state/main/cheats.cpp +++ b/src/state/play/cheats.cpp @@ -9,7 +9,7 @@ using namespace game::util::imgui; using namespace game::util; -namespace game::state::main +namespace game::state::play { void Cheats::update(Resources&, entity::Character& character, Inventory& inventory, Text& text) { diff --git a/src/state/main/cheats.hpp b/src/state/play/cheats.hpp similarity index 86% rename from src/state/main/cheats.hpp rename to src/state/play/cheats.hpp index 74c988b..393326a 100644 --- a/src/state/main/cheats.hpp +++ b/src/state/play/cheats.hpp @@ -5,7 +5,7 @@ #include -namespace game::state::main +namespace game::state::play { class Cheats { diff --git a/src/state/main/debug.cpp b/src/state/play/debug.cpp similarity index 97% rename from src/state/main/debug.cpp rename to src/state/play/debug.cpp index 6d81ca7..4bd30fa 100644 --- a/src/state/main/debug.cpp +++ b/src/state/play/debug.cpp @@ -6,7 +6,7 @@ using namespace game::util::imgui; -namespace game::state::main +namespace game::state::play { void Debug::update(entity::Character& character, entity::Cursor& cursor, ItemManager& itemManager, Canvas& canvas) { diff --git a/src/state/main/debug.hpp b/src/state/play/debug.hpp similarity index 91% rename from src/state/main/debug.hpp rename to src/state/play/debug.hpp index 1214fb9..01d8777 100644 --- a/src/state/main/debug.hpp +++ b/src/state/play/debug.hpp @@ -7,7 +7,7 @@ #include -namespace game::state::main +namespace game::state::play { class Debug { diff --git a/src/state/main/info.cpp b/src/state/play/info.cpp similarity index 99% rename from src/state/main/info.cpp rename to src/state/play/info.cpp index 9f51cfd..4a88da4 100644 --- a/src/state/main/info.cpp +++ b/src/state/play/info.cpp @@ -11,7 +11,7 @@ using namespace game::resource; using namespace game::util; -namespace game::state::main +namespace game::state::play { void Info::update(Resources& resources, entity::Character& character) { diff --git a/src/state/main/info.hpp b/src/state/play/info.hpp similarity index 87% rename from src/state/main/info.hpp rename to src/state/play/info.hpp index 322c193..613cb65 100644 --- a/src/state/main/info.hpp +++ b/src/state/play/info.hpp @@ -5,7 +5,7 @@ #include -namespace game::state::main +namespace game::state::play { class Info { diff --git a/src/state/play/inventory.cpp b/src/state/play/inventory.cpp new file mode 100644 index 0000000..4560a0b --- /dev/null +++ b/src/state/play/inventory.cpp @@ -0,0 +1,348 @@ +#include "inventory.hpp" + +#include +#include +#include +#include + +#include "../../util/color.hpp" +#include "../../util/imgui.hpp" +#include "../../util/imgui/widget.hpp" +#include "../../util/math.hpp" + +using namespace game::util; +using namespace game::util::imgui; +using namespace game::entity; +using namespace game::resource; +using namespace glm; + +namespace game::state::play +{ + void Inventory::tick() + { + for (auto& [i, actor] : actors) + actor.tick(); + } + + void Inventory::update(Resources& resources, ItemManager& itemManager, entity::Character& character) + { + static constexpr auto INFO_CHILD_HEIGHT_MULTIPLIER = 1.0f / 3.0f; + + auto& schema = character.data.itemSchema; + + auto quantity_get = [&](int itemID) -> int& + { + auto& quantity = values[itemID]; + quantity = glm::clamp(0, quantity, schema.quantityMax); + return quantity; + }; + + auto is_possible_to_upgrade_get = [&](const resource::xml::Item::Entry& item) + { + return item.upgradeID.has_value() && item.upgradeCount.has_value() && + schema.idToStringMap.contains(*item.upgradeID); + }; + + auto is_able_to_upgrade_get = [&](const resource::xml::Item::Entry& item, int quantity) + { return is_possible_to_upgrade_get(item) && quantity >= *item.upgradeCount; }; + + auto item_use = [&](int itemID) + { + auto& item = schema.items[itemID]; + auto& category = schema.categories[item.categoryID]; + auto& quantity = quantity_get(itemID); + + if (quantity <= 0) return; + + if (category.isEdible) + { + if (itemManager.items.size() + 1 >= ItemManager::LIMIT) + character.data.itemSchema.sounds.dispose.play(); + else + { + character.data.itemSchema.sounds.summon.play(); + itemManager.queuedItemIDs.emplace_back(itemID); + quantity--; + if (quantity <= 0) selectedItemID = -1; + } + } + else if (item.isToggleSpritesheet) + { + character.spritesheet_set(character.spritesheetType == Character::NORMAL ? Character::ALTERNATE + : Character::NORMAL); + character.data.alternateSpritesheet.sound.play(); + quantity--; + } + }; + + auto item_upgrade = [&](int itemID, bool isAll) + { + auto& item = schema.items[itemID]; + auto& quantity = quantity_get(itemID); + + if (!is_possible_to_upgrade_get(item)) + { + schema.sounds.upgradeFail.play(); + return; + } + + if (!is_able_to_upgrade_get(item, quantity)) + { + schema.sounds.upgradeFail.play(); + return; + } + + if (isAll) + { + while (quantity >= *item.upgradeCount) + { + values.at(*item.upgradeID)++; + quantity -= *item.upgradeCount; + } + } + else + { + values.at(*item.upgradeID)++; + quantity -= *item.upgradeCount; + } + + schema.sounds.upgrade.play(); + + if (quantity < *item.upgradeCount && selectedItemID == itemID) selectedItemID = *item.upgradeID; + }; + + auto item_canvas_get = [&](int itemID, ImVec2 size) + { + if (!actors.contains(itemID)) + { + actors[itemID] = Actor(schema.anm2s[itemID], {}, Actor::SET); + rects[itemID] = actors[itemID].rect(); + } + + auto& rect = rects[itemID]; + auto rectSize = vec2(rect.z, rect.w); + auto previewScale = (size.x <= 0.0f || size.y <= 0.0f || rectSize.x <= 0.0f || rectSize.y <= 0.0f || + !std::isfinite(rectSize.x) || !std::isfinite(rectSize.y)) + ? 0.0f + : std::min(size.x / rectSize.x, size.y / rectSize.y); + + auto previewSize = rectSize * previewScale; + auto canvasSize = ivec2(std::max(1.0f, previewSize.x), std::max(1.0f, previewSize.y)); + if (!canvases.contains(itemID)) canvases.emplace(itemID, Canvas(canvasSize, Canvas::FLIP)); + + auto& canvas = canvases[itemID]; + canvas.zoom = math::to_percent(previewScale); + canvas.pan = vec2(rect.x, rect.y); + canvas.bind(); + canvas.size_set(canvasSize); + canvas.clear(); + actors[itemID].render(resources.shaders[shader::TEXTURE], resources.shaders[shader::RECT], canvas); + canvas.unbind(); + + return std::tuple(canvas, rect); + }; + + if (!itemManager.returnItemIDs.empty()) + { + for (auto& id : itemManager.returnItemIDs) + values[id]++; + itemManager.returnItemIDs.clear(); + } + + if (ImGui::BeginChild("##Inventory Child", ImGui::GetContentRegionAvail(), ImGuiChildFlags_None, + ImGuiWindowFlags_NoScrollbar)) + { + auto inventoryCount = count(); + auto available = ImGui::GetContentRegionAvail(); + auto isItemSelected = selectedItemID >= 0 && selectedItemID < (int)schema.items.size(); + auto isInfoVisible = isItemSelected || inventoryCount == 0; + auto infoChildHeight = + isInfoVisible ? available.y * INFO_CHILD_HEIGHT_MULTIPLIER + ImGui::GetStyle().ItemSpacing.y * 2.0f : 0.0f; + auto inventoryChildHeight = + isInfoVisible ? available.y - infoChildHeight - ImGui::GetStyle().ItemSpacing.y : available.y; + auto childSize = ImVec2(available.x, inventoryChildHeight); + auto infoChildSize = ImVec2(available.x, infoChildHeight); + + if (ImGui::BeginChild("##Inventory List Child", childSize)) + { + auto cursorPos = ImGui::GetCursorPos(); + auto cursorStartX = ImGui::GetCursorPosX(); + bool isAnyInventoryItemHovered{}; + + auto size = ImVec2(SIZE, SIZE); + + for (int i = 0; i < (int)schema.items.size(); i++) + { + auto& item = schema.items[i]; + auto& quantity = quantity_get(i); + auto& rarity = schema.rarities[item.rarityID]; + + if (rarity.isHidden && quantity <= 0) continue; + + ImGui::PushID(i); + + ImGui::SetCursorPos(cursorPos); + auto cursorScreenPos = ImGui::GetCursorScreenPos(); + auto [canvas, rect] = item_canvas_get(i, size); + auto isSelected = selectedItemID == i; + + if (isSelected) + { + auto selectedColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); + ImGui::PushStyleColor(ImGuiCol_Button, selectedColor); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, selectedColor); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, selectedColor); + } + + auto isPressed = + WIDGET_FX(ImGui::ImageButton("##Image Button", canvas.texture, size, ImVec2(), ImVec2(1, 1), ImVec4(), + quantity <= 0 ? ImVec4(0, 0, 0, 0.5f) : ImVec4(1, 1, 1, 1))); + if (isSelected) ImGui::PopStyleColor(3); + isAnyInventoryItemHovered = isAnyInventoryItemHovered || ImGui::IsItemHovered(); + if (isPressed) selectedItemID = i; + if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && quantity > 0) item_use(i); + + ImGui::PushFont(ImGui::GetFont(), Font::BIG); + + auto text = std::format("x{}", quantity); + auto textPos = ImVec2(cursorScreenPos.x + size.x - ImGui::CalcTextSize(text.c_str()).x, + cursorScreenPos.y + size.y - ImGui::GetTextLineHeightWithSpacing()); + ImGui::GetWindowDrawList()->AddText(textPos, ImGui::GetColorU32(ImGui::GetStyleColorVec4(ImGuiCol_Text)), + text.c_str()); + ImGui::PopFont(); + + auto increment = ImGui::GetItemRectSize().x + ImGui::GetStyle().ItemSpacing.x; + cursorPos.x += increment; + + if (cursorPos.x + increment > ImGui::GetContentRegionAvail().x) + { + cursorPos.x = cursorStartX; + cursorPos.y += increment; + } + + ImGui::PopID(); + } + + if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !isAnyInventoryItemHovered) + selectedItemID = -1; + } + ImGui::EndChild(); + + isItemSelected = selectedItemID >= 0 && selectedItemID < (int)schema.items.size(); + auto selectedQuantity = isItemSelected ? quantity_get(selectedItemID) : 0; + auto isSelectedItemKnown = isItemSelected && selectedQuantity > 0; + + if (isInfoVisible && + ImGui::BeginChild("##Info Child", infoChildSize, ImGuiChildFlags_None, ImGuiWindowFlags_NoScrollbar)) + { + ImGui::Separator(); + auto isButtonChildVisible = selectedQuantity > 0; + ImGui::PushFont(resources.font.get(), Font::BIG); + auto buttonRowHeight = ImGui::GetFrameHeight(); + auto buttonChildHeight = + isButtonChildVisible ? buttonRowHeight * 2.0f + ImGui::GetStyle().ItemSpacing.y * 5.0f : 0.0f; + auto buttonChildSize = ImVec2(ImGui::GetContentRegionAvail().x, buttonChildHeight); + auto infoBodySize = + ImVec2(ImGui::GetContentRegionAvail().x, + ImGui::GetContentRegionAvail().y - buttonChildSize.y - + (isButtonChildVisible ? ImGui::GetStyle().ItemSpacing.y : 0.0f)); + ImGui::PopFont(); + + if (ImGui::BeginChild("##Info Content Child", infoBodySize)) + { + if (!isItemSelected) + { + ImGui::PushFont(ImGui::GetFont(), Font::BIG); + ImGui::TextWrapped("%s", "Check the \"Arcade\" tab to earn rewards!"); + ImGui::PopFont(); + } + else + { + auto& item = schema.items[selectedItemID]; + auto& category = schema.categories[item.categoryID]; + auto& rarity = schema.rarities[item.rarityID]; + + if (isSelectedItemKnown) + { + ImGui::PushFont(ImGui::GetFont(), Font::BIG); + ImGui::TextWrapped("%s (x%i)", item.name.c_str(), selectedQuantity); + ImGui::PopFont(); + + ImGui::Separator(); + ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(imgui::to_imvec4(color::GRAY))); + ImGui::TextWrapped("-- %s (%s) --", category.name.c_str(), rarity.name.c_str()); + if (item.flavorID.has_value()) + ImGui::TextWrapped("Flavor: %s", schema.flavors[*item.flavorID].name.c_str()); + if (item.calories.has_value()) ImGui::TextWrapped("%0.0f kcal", *item.calories); + if (item.digestionBonus.has_value()) + { + if (*item.digestionBonus > 0) + ImGui::TextWrapped("Digestion Rate Bonus: +%0.2f%% / sec", *item.digestionBonus * 60.0f); + else if (*item.digestionBonus < 0) + ImGui::TextWrapped("Digestion Rate Penalty: %0.2f%% / sec", *item.digestionBonus * 60.0f); + } + if (item.eatSpeedBonus.has_value()) + { + if (*item.eatSpeedBonus > 0) + ImGui::TextWrapped("Eat Speed Bonus: +%0.2f%% / sec", *item.eatSpeedBonus); + else if (*item.eatSpeedBonus < 0) + ImGui::TextWrapped("Eat Speed Penalty: %0.2f%% / sec", *item.eatSpeedBonus); + } + if (is_possible_to_upgrade_get(item)) + ImGui::TextWrapped("Upgrade: %ix -> %s", *item.upgradeCount, + schema.idToStringMap.at(*item.upgradeID).c_str()); + ImGui::PopStyleColor(); + + ImGui::Separator(); + ImGui::TextWrapped("%s", item.description.c_str()); + } + else + { + ImGui::PushFont(ImGui::GetFont(), Font::BIG); + ImGui::TextWrapped("%s", "???"); + ImGui::PopFont(); + } + } + } + ImGui::EndChild(); + + if (isButtonChildVisible && + ImGui::BeginChild("##Info Actions Child", buttonChildSize, ImGuiChildFlags_None, + ImGuiWindowFlags_NoScrollbar)) + { + auto canUseSelectedItem = true; + auto canUpgradeSelectedItem = is_able_to_upgrade_get(schema.items[selectedItemID], selectedQuantity); + auto rowTwoButtonSize = row_widget_size_get(2); + + ImGui::Separator(); + ImGui::Dummy(ImVec2(0, ImGui::GetStyle().ItemSpacing.y)); + + ImGui::PushFont(ImGui::GetFont(), Font::BIG); + + ImGui::BeginDisabled(!canUseSelectedItem); + if (WIDGET_FX(ImGui::Button("Spawn", {ImGui::GetContentRegionAvail().x, 0}))) item_use(selectedItemID); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(!canUpgradeSelectedItem); + if (WIDGET_FX(ImGui::Button("Upgrade", rowTwoButtonSize))) item_upgrade(selectedItemID, false); + ImGui::SameLine(); + if (WIDGET_FX(ImGui::Button("Upgrade All", rowTwoButtonSize))) item_upgrade(selectedItemID, true); + ImGui::EndDisabled(); + + ImGui::PopFont(); + } + if (isButtonChildVisible) ImGui::EndChild(); + } + if (isInfoVisible) ImGui::EndChild(); + } + ImGui::EndChild(); + } + + int Inventory::count() + { + int count{}; + for (auto& [type, quantity] : values) + count += quantity; + return count; + } +} diff --git a/src/state/main/inventory.hpp b/src/state/play/inventory.hpp similarity index 89% rename from src/state/main/inventory.hpp rename to src/state/play/inventory.hpp index 2901e64..2737a14 100644 --- a/src/state/main/inventory.hpp +++ b/src/state/play/inventory.hpp @@ -8,7 +8,7 @@ #include -namespace game::state::main +namespace game::state::play { class Inventory { @@ -19,6 +19,7 @@ namespace game::state::main std::unordered_map actors{}; std::unordered_map rects{}; std::unordered_map canvases{}; + int selectedItemID{-1}; void tick(); void update(Resources&, ItemManager&, entity::Character&); diff --git a/src/state/main/item_manager.cpp b/src/state/play/item_manager.cpp similarity index 99% rename from src/state/main/item_manager.cpp rename to src/state/play/item_manager.cpp index e34dcc9..1115151 100644 --- a/src/state/main/item_manager.cpp +++ b/src/state/play/item_manager.cpp @@ -13,7 +13,7 @@ using namespace game::resource; using namespace game::util; using namespace glm; -namespace game::state::main +namespace game::state::play { void ItemManager::update(entity::Character& character, entity::Cursor& cursor, AreaManager& areaManager, Text& text, const glm::vec4& bounds, Canvas& canvas) diff --git a/src/state/main/item_manager.hpp b/src/state/play/item_manager.hpp similarity index 97% rename from src/state/main/item_manager.hpp rename to src/state/play/item_manager.hpp index 2664693..03d6fd4 100644 --- a/src/state/main/item_manager.hpp +++ b/src/state/play/item_manager.hpp @@ -7,7 +7,7 @@ #include "area_manager.hpp" #include "text.hpp" -namespace game::state::main +namespace game::state::play { class ItemManager { diff --git a/src/state/main/menu.cpp b/src/state/play/menu.cpp similarity index 86% rename from src/state/main/menu.cpp rename to src/state/play/menu.cpp index 267c671..71a2035 100644 --- a/src/state/main/menu.cpp +++ b/src/state/play/menu.cpp @@ -1,6 +1,7 @@ #include "menu.hpp" #include "../../util/imgui.hpp" +#include "../../util/imgui/style.hpp" #include "../../util/imgui/widget.hpp" #include @@ -8,12 +9,17 @@ using namespace game::util; using namespace game::util::imgui; -namespace game::state::main +namespace game::state::play { void Menu::tick() { inventory.tick(); - play.tick(); + skillCheck.tick(); + } + + void Menu::color_set_check(Resources& resources, entity::Character& character) + { + imgui::style::color_set(resources.settings.isUseCharacterColor ? character.data.color : resources.settings.color); } void Menu::update(Resources& resources, ItemManager& itemManager, entity::Character& character, @@ -61,13 +67,13 @@ namespace game::state::main ImGui::EndTabItem(); } - if (WIDGET_FX(ImGui::BeginTabItem("Play"))) + if (WIDGET_FX(ImGui::BeginTabItem("Arcade"))) { - play.update(resources, character, inventory, text); + skillCheck.update(resources, character, inventory, text); ImGui::EndTabItem(); } - if (WIDGET_FX(ImGui::BeginTabItem("Items"))) + if (WIDGET_FX(ImGui::BeginTabItem("Inventory"))) { inventory.update(resources, itemManager, character); ImGui::EndTabItem(); @@ -75,13 +81,14 @@ namespace game::state::main if (WIDGET_FX(ImGui::BeginTabItem("Stats"))) { - stats.update(resources, play, character); + stats.update(resources, skillCheck, character); ImGui::EndTabItem(); } if (WIDGET_FX(ImGui::BeginTabItem("Settings"))) { - configuration.update(resources, Configuration::MAIN); + settingsMenu.update(resources, SettingsMenu::PLAY); + if (settingsMenu.isJustColorSet) color_set_check(resources, character); ImGui::EndTabItem(); } @@ -91,11 +98,13 @@ namespace game::state::main ImGui::EndTabItem(); } - if (isDebug && WIDGET_FX(ImGui::BeginTabItem("Debug"))) +#if DEBUG + if (WIDGET_FX(ImGui::BeginTabItem("Debug"))) { debug.update(character, cursor, itemManager, canvas); ImGui::EndTabItem(); } +#endif } ImGui::EndTabBar(); } diff --git a/src/state/main/menu.hpp b/src/state/play/menu.hpp similarity index 69% rename from src/state/main/menu.hpp rename to src/state/play/menu.hpp index e09222b..f4cb32f 100644 --- a/src/state/main/menu.hpp +++ b/src/state/play/menu.hpp @@ -2,37 +2,35 @@ #include -#include "../configuration.hpp" +#include "../settings_menu.hpp" +#include "arcade/skill_check.hpp" #include "chat.hpp" #include "cheats.hpp" #include "debug.hpp" -#include "play.hpp" #include "stats.hpp" #include "text.hpp" #include "../../util/imgui/window_slide.hpp" -namespace game::state::main +namespace game::state::play { class Menu { public: - Play play; + SkillCheck skillCheck; Chat chat; Cheats cheats; Debug debug; Stats stats; Inventory inventory; - state::Configuration configuration; + state::SettingsMenu settingsMenu; #if DEBUG + bool isCheats{true}; +#elif bool isCheats{}; - bool isDebug{true}; -#else - bool isCheats{}; - bool isDebug{}; #endif bool isOpen{true}; @@ -41,5 +39,6 @@ namespace game::state::main void tick(); void update(Resources&, ItemManager&, entity::Character&, entity::Cursor&, Text&, Canvas&); + void color_set_check(Resources&, entity::Character&); }; } diff --git a/src/state/main/stats.cpp b/src/state/play/stats.cpp similarity index 61% rename from src/state/main/stats.cpp rename to src/state/play/stats.cpp index 3a76b92..7857900 100644 --- a/src/state/main/stats.cpp +++ b/src/state/play/stats.cpp @@ -7,9 +7,9 @@ using namespace game::resource; using namespace game::util; -namespace game::state::main +namespace game::state::play { - void Stats::update(Resources& resources, Play& play, entity::Character& character) + void Stats::update(Resources& resources, SkillCheck& skillCheck, entity::Character& character) { ImGui::PushFont(ImGui::GetFont(), Font::BIG); ImGui::TextUnformatted(character.data.name.c_str()); @@ -17,7 +17,7 @@ namespace game::state::main ImGui::Separator(); - auto& playSchema = character.data.playSchema; + auto& skillCheckSchema = character.data.skillCheckSchema; auto& system = resources.settings.measurementSystem; auto weight = character.weight_get(system); auto weightUnit = system == measurement::IMPERIAL ? "lbs" : "kg"; @@ -32,17 +32,17 @@ namespace game::state::main ImGui::Text("Total Calories Consumed: %0.0f kcal", character.totalCaloriesConsumed); ImGui::Text("Total Food Items Eaten: %i", character.totalFoodItemsEaten); - ImGui::SeparatorText("Play"); + ImGui::SeparatorText("Skill Check"); - ImGui::Text("Best: %i pts (%ix)", play.highScore, play.bestCombo); - ImGui::Text("Total Plays: %i", play.totalPlays); + ImGui::Text("Best: %i pts (%ix)", skillCheck.highScore, skillCheck.bestCombo); + ImGui::Text("Total Skill Checks: %i", skillCheck.totalPlays); - for (int i = 0; i < (int)playSchema.grades.size(); i++) + for (int i = 0; i < (int)skillCheckSchema.grades.size(); i++) { - auto& grade = playSchema.grades[i]; - ImGui::Text("%s: %i", grade.namePlural.c_str(), play.gradeCounts[i]); + auto& grade = skillCheckSchema.grades[i]; + ImGui::Text("%s: %i", grade.namePlural.c_str(), skillCheck.gradeCounts[i]); } - ImGui::Text("Accuracy: %0.2f%%", play.accuracy_score_get(character)); + ImGui::Text("Accuracy: %0.2f%%", skillCheck.accuracy_score_get(character)); } } diff --git a/src/state/main/stats.hpp b/src/state/play/stats.hpp similarity index 53% rename from src/state/main/stats.hpp rename to src/state/play/stats.hpp index cd561a4..e3b7c55 100644 --- a/src/state/main/stats.hpp +++ b/src/state/play/stats.hpp @@ -3,15 +3,15 @@ #include "../../entity/character.hpp" #include "../../resources.hpp" -#include "play.hpp" +#include "arcade/skill_check.hpp" #include -namespace game::state::main +namespace game::state::play { class Stats { public: - void update(Resources&, Play&, entity::Character&); + void update(Resources&, SkillCheck&, entity::Character&); }; } diff --git a/src/state/main/text.cpp b/src/state/play/text.cpp similarity index 99% rename from src/state/main/text.cpp rename to src/state/play/text.cpp index 9046214..1ddd0f6 100644 --- a/src/state/main/text.cpp +++ b/src/state/play/text.cpp @@ -12,7 +12,7 @@ using namespace game::util; -namespace game::state::main +namespace game::state::play { const char* utf8_advance_chars(const char* text, const char* end, int count) { diff --git a/src/state/main/text.hpp b/src/state/play/text.hpp similarity index 94% rename from src/state/main/text.hpp rename to src/state/play/text.hpp index 4695d0a..643b66e 100644 --- a/src/state/main/text.hpp +++ b/src/state/play/text.hpp @@ -6,7 +6,7 @@ #include "../../resources.hpp" -namespace game::state::main +namespace game::state::play { class Text { diff --git a/src/state/main/toasts.cpp b/src/state/play/toasts.cpp similarity index 98% rename from src/state/main/toasts.cpp rename to src/state/play/toasts.cpp index fc687ae..2437b36 100644 --- a/src/state/main/toasts.cpp +++ b/src/state/play/toasts.cpp @@ -3,7 +3,7 @@ #include #include -namespace game::state::main +namespace game::state::play { void Toasts::tick() { diff --git a/src/state/main/toasts.hpp b/src/state/play/toasts.hpp similarity index 91% rename from src/state/main/toasts.hpp rename to src/state/play/toasts.hpp index 07a112a..88e47f8 100644 --- a/src/state/main/toasts.hpp +++ b/src/state/play/toasts.hpp @@ -3,7 +3,7 @@ #include #include -namespace game::state::main +namespace game::state::play { class Toasts { diff --git a/src/state/main/tools.cpp b/src/state/play/tools.cpp similarity index 90% rename from src/state/main/tools.cpp rename to src/state/play/tools.cpp index 6c01bb5..09db70b 100644 --- a/src/state/main/tools.cpp +++ b/src/state/play/tools.cpp @@ -8,7 +8,7 @@ using namespace game::util; using namespace game::util::imgui; -namespace game::state::main +namespace game::state::play { void Tools::update(entity::Character& character, entity::Cursor& cursor, World& world, World::Focus focus, Canvas& canvas) @@ -47,21 +47,20 @@ namespace game::state::main { auto buttonSize = imgui::to_imvec2(vec2(ImGui::GetContentRegionAvail().x)); - auto cursor_mode_button = [&](const char* name, InteractType mode) + auto cursor_mode_button = [&](const std::string& name, int interactTypeID) { - auto isMode = cursor.mode == mode; + auto isMode = cursor.interactTypeID == interactTypeID; ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyleColorVec4(isMode ? ImGuiCol_ButtonHovered : ImGuiCol_Button)); - if (WIDGET_FX(ImGui::Button(name, buttonSize))) cursor.mode = mode; + if (WIDGET_FX(ImGui::Button(name.c_str(), buttonSize))) cursor.interactTypeID = interactTypeID; ImGui::PopStyleColor(); }; if (WIDGET_FX(ImGui::Button("Home", buttonSize))) world.character_focus(character, canvas, focus); ImGui::SetItemTooltip("%s", "Reset camera view.\n(Shortcut: Home)"); - cursor_mode_button("Rub", InteractType::RUB); - cursor_mode_button("Kiss", InteractType::KISS); - cursor_mode_button("Smack", InteractType::SMACK); + for (int i = 0; i < (int)character.data.interactTypeNames.size(); i++) + cursor_mode_button(character.data.interactTypeNames[i], i); } ImGui::End(); } diff --git a/src/state/main/tools.hpp b/src/state/play/tools.hpp similarity index 91% rename from src/state/main/tools.hpp rename to src/state/play/tools.hpp index 308d67a..606f44e 100644 --- a/src/state/main/tools.hpp +++ b/src/state/play/tools.hpp @@ -5,7 +5,7 @@ #include "../../util/imgui/window_slide.hpp" #include "world.hpp" -namespace game::state::main +namespace game::state::play { class Tools { diff --git a/src/state/main/world.cpp b/src/state/play/world.cpp similarity index 99% rename from src/state/main/world.cpp rename to src/state/play/world.cpp index d4780c5..62dd594 100644 --- a/src/state/main/world.cpp +++ b/src/state/play/world.cpp @@ -8,7 +8,7 @@ using namespace game::util; -namespace game::state::main +namespace game::state::play { void World::set(entity::Character& character, Canvas& canvas, Focus focus) { diff --git a/src/state/main/world.hpp b/src/state/play/world.hpp similarity index 93% rename from src/state/main/world.hpp rename to src/state/play/world.hpp index f958306..9b7624f 100644 --- a/src/state/main/world.hpp +++ b/src/state/play/world.hpp @@ -1,12 +1,12 @@ #pragma once -#include "../../canvas.hpp" +#include "../../render/canvas.hpp" #include "../../entity/character.hpp" #include "character_manager.hpp" #include "item_manager.hpp" -namespace game::state::main +namespace game::state::play { class World { diff --git a/src/state/select.hpp b/src/state/select.hpp index 066f83d..fc91676 100644 --- a/src/state/select.hpp +++ b/src/state/select.hpp @@ -1,6 +1,6 @@ #pragma once -#include "../canvas.hpp" +#include "../render/canvas.hpp" #include "select/characters.hpp" #include "select/info.hpp" @@ -21,4 +21,4 @@ namespace game::state void update(Resources&); void render(Resources&, Canvas&); }; -}; \ No newline at end of file +}; diff --git a/src/state/select/characters.cpp b/src/state/select/characters.cpp index d7ac6c2..7f0e4d1 100644 --- a/src/state/select/characters.cpp +++ b/src/state/select/characters.cpp @@ -1,10 +1,9 @@ #include "characters.hpp" -#include - +#include "../../util/imgui/style.hpp" #include "../../util/imgui/widget.hpp" -using namespace game::util::imgui; +using namespace game::util; namespace game::state::select { @@ -39,6 +38,7 @@ namespace game::state::select ImGui::PushID(i); ImGui::SetCursorPos(cursorPos); + imgui::style::color_set(character.color); auto isSelected = i == characterIndex; @@ -64,13 +64,14 @@ namespace game::state::select } ImGui::PopID(); + imgui::style::color_set(resources.settings.color); } ImGui::EndTabItem(); } - if (WIDGET_FX(ImGui::BeginTabItem("Configuration"))) + if (WIDGET_FX(ImGui::BeginTabItem("Settings"))) { - configuration.update(resources); + settingsMenu.update(resources); ImGui::EndTabItem(); } ImGui::EndTabBar(); diff --git a/src/state/select/characters.hpp b/src/state/select/characters.hpp index 38b3e06..4109842 100644 --- a/src/state/select/characters.hpp +++ b/src/state/select/characters.hpp @@ -1,15 +1,15 @@ #pragma once #include "../../resources.hpp" -#include "../configuration.hpp" +#include "../settings_menu.hpp" namespace game::state::select { class Characters { public: - Configuration configuration; + SettingsMenu settingsMenu; void update(Resources&, int& characterIndex); }; -} \ No newline at end of file +} diff --git a/src/state/select/info.cpp b/src/state/select/info.cpp index 5dd1dc4..0756af6 100644 --- a/src/state/select/info.cpp +++ b/src/state/select/info.cpp @@ -2,6 +2,7 @@ #include "../../util/color.hpp" #include "../../util/imgui.hpp" +#include "../../util/imgui/style.hpp" #include "../../util/imgui/widget.hpp" #include "../../util/vector.hpp" @@ -18,6 +19,7 @@ namespace game::state::select auto& style = ImGui::GetStyle(); auto viewport = ImGui::GetMainViewport(); + auto& character = resources.characterPreviews[characterIndex]; auto size = ImVec2(viewport->Size.x / 2.0f - (style.WindowPadding.x * 2.0f), (viewport->Size.y / 2.0f) - (style.WindowPadding.y * 2.0f)); @@ -25,12 +27,12 @@ namespace game::state::select ImGui::SetNextWindowSize(size); ImGui::SetNextWindowPos(pos); + imgui::style::color_set(character.color); if (ImGui::Begin("##Info", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar)) { - auto& character = resources.characterPreviews[characterIndex]; auto& save = character.save; auto& system = resources.settings.measurementSystem; auto& weight = save.is_valid() ? save.weight : character.weight; @@ -123,5 +125,6 @@ namespace game::state::select } } ImGui::End(); + imgui::style::color_set(resources.settings.color); } } diff --git a/src/state/select/preview.cpp b/src/state/select/preview.cpp index c2c65b5..a95aa24 100644 --- a/src/state/select/preview.cpp +++ b/src/state/select/preview.cpp @@ -4,6 +4,7 @@ #include #include "../../util/imgui.hpp" +#include "../../util/imgui/style.hpp" #include "../../util/imgui/widget.hpp" #include "../../util/vector.hpp" @@ -25,13 +26,14 @@ namespace game::state::select auto& style = ImGui::GetStyle(); auto viewport = ImGui::GetMainViewport(); - + auto& character = resources.characterPreviews[characterIndex]; auto size = ImVec2(viewport->Size.x / 2.0f - (style.WindowPadding.x * 2.0f), (viewport->Size.y / 2.0f) - (style.WindowPadding.y * 2.0f)); auto pos = ImVec2(style.WindowPadding.x, style.WindowPadding.y); ImGui::SetNextWindowSize(size); ImGui::SetNextWindowPos(pos); + imgui::style::color_set(character.color); if (ImGui::Begin("##Preview", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | @@ -39,8 +41,6 @@ namespace game::state::select { if (ImGui::BeginTabBar("##Preview Tab Bar")) { - auto& character = resources.characterPreviews[characterIndex]; - auto available = ImGui::GetContentRegionAvail(); auto availableSize = imgui::to_vec2(available); auto textureSize = vec2(character.render.size); @@ -106,5 +106,6 @@ namespace game::state::select } } ImGui::End(); + imgui::style::color_set(resources.settings.color); } } diff --git a/src/state/configuration.cpp b/src/state/settings_menu.cpp similarity index 79% rename from src/state/configuration.cpp rename to src/state/settings_menu.cpp index 82165b1..036097d 100644 --- a/src/state/configuration.cpp +++ b/src/state/settings_menu.cpp @@ -1,4 +1,4 @@ -#include "configuration.hpp" +#include "settings_menu.hpp" #include #include @@ -13,13 +13,15 @@ using namespace game::util::imgui; namespace game::state { - void Configuration::update(Resources& resources, Mode mode) + void SettingsMenu::update(Resources& resources, Mode mode) { auto& settings = resources.settings; auto& measurementSystem = settings.measurementSystem; auto& volume = settings.volume; auto& color = settings.color; + isJustColorSet = false; + ImGui::SeparatorText("Measurement System"); WIDGET_FX(ImGui::RadioButton("Metric", (int*)&measurementSystem, measurement::METRIC)); ImGui::SetItemTooltip("%s", "Use kilograms (kg)."); @@ -34,10 +36,18 @@ namespace game::state ImGui::SeparatorText("Appearance"); + if (WIDGET_FX(ImGui::Checkbox("Use Character Color", &settings.isUseCharacterColor))) isJustColorSet = true; + ImGui::SetItemTooltip("When playing, the UI will use the character's preset UI color."); + ImGui::SameLine(); + ImGui::BeginDisabled(settings.isUseCharacterColor); if (WIDGET_FX( ImGui::ColorEdit3("Color", value_ptr(color), ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoTooltip))) + { style::color_set(color); + isJustColorSet = true; + } ImGui::SetItemTooltip("%s", "Change the UI color."); + ImGui::EndDisabled(); ImGui::Separator(); if (WIDGET_FX(ImGui::Button("Reset to Default", ImVec2(-FLT_MIN, 0)))) @@ -46,7 +56,7 @@ namespace game::state style::color_set(settings.color); } - if (mode == MAIN) + if (mode == PLAY) { ImGui::Separator(); diff --git a/src/state/configuration.hpp b/src/state/settings_menu.hpp similarity index 78% rename from src/state/configuration.hpp rename to src/state/settings_menu.hpp index 8eaaf75..ca7b708 100644 --- a/src/state/configuration.hpp +++ b/src/state/settings_menu.hpp @@ -4,18 +4,19 @@ namespace game::state { - class Configuration + class SettingsMenu { public: enum Mode { SELECT, - MAIN + PLAY }; bool isGoToSelect{}; bool isSave{}; + bool isJustColorSet{}; void update(Resources&, Mode = SELECT); }; -} \ No newline at end of file +} diff --git a/src/util/interact_type.hpp b/src/util/interact_type.hpp deleted file mode 100644 index a44bace..0000000 --- a/src/util/interact_type.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -namespace game -{ -#define LIST \ - X(RUB, "Rub") \ - X(KISS, "Kiss") \ - X(SMACK, "Smack") - - enum InteractType - { -#define X(symbol, string) symbol, - LIST -#undef X - }; - - static constexpr const char* INTERACT_TYPE_STRINGS[] = { -#define X(symbol, string) string, - LIST -#undef X - }; - -#undef LIST -} \ No newline at end of file