a (not so) mini update

This commit is contained in:
2026-04-01 02:08:50 -04:00
parent fb6f902f28
commit af04a9b313
64 changed files with 1158 additions and 583 deletions

View File

@@ -1,4 +1,5 @@
#include "play.hpp"
#include "play/style.hpp"
#include <array>
#include <glm/glm.hpp>
@@ -11,12 +12,25 @@
#include "../util/math.hpp"
using namespace game::resource;
using namespace game::resource::xml;
using namespace game::util;
using namespace game::state::play;
using namespace glm;
namespace game::state
{
namespace
{
int durability_animation_index_get(const resource::xml::Item& schema, const resource::xml::Anm2& anm2, int durability,
int durabilityMax)
{
if (durability >= durabilityMax) return -1;
auto animationName = schema.animations.chew + std::to_string(std::max(0, durability));
return anm2.animationMap.contains(animationName) ? anm2.animationMap.at(animationName) : -1;
}
}
World::Focus Play::focus_get()
{
if (!isWindows) return World::CENTER;
@@ -40,9 +54,10 @@ namespace game::state
character =
entity::Character(data, vec2(World::BOUNDS.x + World::BOUNDS.z * 0.5f, World::BOUNDS.w - World::BOUNDS.y));
character.digestionRate = glm::clamp(data.digestionRateMin, character.digestionRate, data.digestionRateMax);
character.eatSpeed = glm::clamp(data.eatSpeedMin, character.eatSpeed, data.eatSpeedMax);
character.capacity = glm::clamp(data.capacityMin, character.capacity, data.capacityMax);
character.digestionRate =
glm::clamp(character.digestionRate, (float)data.digestionRateMin, (float)data.digestionRateMax);
character.eatSpeed = glm::clamp(character.eatSpeed, (float)data.eatSpeedMin, (float)data.eatSpeedMax);
character.capacity = glm::clamp(character.capacity, (float)data.capacityMin, (float)data.capacityMax);
auto isAlternateSpritesheet =
(game == NEW_GAME && math::random_percent_roll(data.alternateSpritesheet.chanceOnNewGame));
@@ -71,29 +86,34 @@ namespace game::state
for (auto& item : saveData.items)
{
auto& anm2 = itemSchema.anm2s.at(item.id);
auto chewAnimation = itemSchema.animations.chew + std::to_string(item.chewCount);
auto animationIndex = item.chewCount > 0 ? anm2.animationMap[chewAnimation] : -1;
auto& schemaItem = itemSchema.items.at(item.id);
auto durabilityMax = schemaItem.durability.value_or(itemSchema.durability);
auto animationIndex = durability_animation_index_get(itemSchema, anm2, item.durability, durabilityMax);
auto& saveItem = itemSchema.anm2s.at(item.id);
itemManager.items.emplace_back(saveItem, item.position, item.id, item.chewCount, animationIndex, item.velocity,
itemManager.items.emplace_back(saveItem, item.position, item.id, item.durability, animationIndex, item.velocity,
item.rotation);
}
imgui::style::rounding_set(menuSchema.rounding);
imgui::widget::sounds_set(&menuSchema.sounds.hover, &menuSchema.sounds.select);
menu.color_set_check(resources, character);
play::style::color_set(resources, character);
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();
menu.arcade = Arcade(character);
menu.arcade.skillCheck.totalPlays = saveData.totalPlays;
menu.arcade.skillCheck.highScore = saveData.highScore;
menu.arcade.skillCheck.bestCombo = saveData.bestCombo;
menu.arcade.skillCheck.gradeCounts = saveData.gradeCounts;
menu.arcade.skillCheck.isHighScoreAchieved = saveData.highScore > 0 ? true : false;
text.entry = nullptr;
text.isEnabled = false;
#if DEBUG
menu.isCheats = true;
#else
menu.isCheats = false;
#endif
isPostgame = saveData.isPostgame;
if (character.stage_get() >= character.stage_max_get()) isPostgame = true;
if (isPostgame) menu.isCheats = true;
@@ -190,7 +210,7 @@ namespace game::state
menu.isCheats = true;
cheatCodeIndex = 0;
cheatCodeStartTime = 0.0;
toasts.push("Cheats unlocked!");
toasts.push(character.data.strings.get(Strings::ToastCheatsUnlocked));
character.data.menuSchema.sounds.cheatsActivated.play();
}
}
@@ -338,10 +358,10 @@ namespace game::state
save.digestionTimer = character.digestionTimer;
save.totalCaloriesConsumed = character.totalCaloriesConsumed;
save.totalFoodItemsEaten = character.totalFoodItemsEaten;
save.totalPlays = menu.skillCheck.totalPlays;
save.highScore = menu.skillCheck.highScore;
save.bestCombo = menu.skillCheck.bestCombo;
save.gradeCounts = menu.skillCheck.gradeCounts;
save.totalPlays = menu.arcade.skillCheck.totalPlays;
save.highScore = menu.arcade.skillCheck.highScore;
save.bestCombo = menu.arcade.skillCheck.bestCombo;
save.gradeCounts = menu.arcade.skillCheck.gradeCounts;
save.isPostgame = isPostgame;
save.isAlternateSpritesheet = character.spritesheetType == entity::Character::ALTERNATE;
@@ -352,7 +372,7 @@ namespace game::state
}
for (auto& item : itemManager.items)
save.items.emplace_back(item.schemaID, item.chewCount, item.position, item.velocity,
save.items.emplace_back(item.schemaID, item.durability, item.position, item.velocity,
*item.overrides[item.rotationOverrideID].frame.rotation);
save.isValid = true;
@@ -360,6 +380,6 @@ namespace game::state
resources.character_save_set(characterIndex, save);
save.serialize(character.data.save_path_get());
toasts.push("Saving...");
toasts.push(character.data.strings.get(Strings::ToastSaving));
}
};

76
src/state/play/arcade.cpp Normal file
View File

@@ -0,0 +1,76 @@
#include "arcade.hpp"
#include "../../util/imgui/widget.hpp"
using namespace game::util::imgui;
using namespace game::resource::xml;
namespace game::state::play
{
Arcade::Arcade(entity::Character& character) : skillCheck(character) {}
void Arcade::tick() { skillCheck.tick(); }
void Arcade::update(Resources& resources, entity::Character& character, Inventory& inventory, Text& text)
{
auto available = ImGui::GetContentRegionAvail();
auto& strings = character.data.strings;
if (view == SKILL_CHECK)
{
if (skillCheck.update(resources, character, inventory, text)) view = MENU;
return;
}
auto buttonHeight = ImGui::GetFrameHeightWithSpacing();
auto childSize = ImVec2(available.x, std::max(0.0f, available.y - buttonHeight));
if (ImGui::BeginChild("##Arcade Child", childSize))
{
if (view == MENU)
{
auto buttonWidth = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.x) * 0.5f;
ImGui::PushFont(ImGui::GetFont(), resource::Font::HEADER_2);
ImGui::TextUnformatted(strings.get(Strings::ArcadeSkillCheckName).c_str());
ImGui::PopFont();
ImGui::Separator();
ImGui::TextWrapped("%s", strings.get(Strings::ArcadeSkillCheckDescription).c_str());
ImGui::Separator();
if (WIDGET_FX(ImGui::Button(strings.get(Strings::ArcadePlayButton).c_str(), ImVec2(buttonWidth, 0))))
view = SKILL_CHECK;
ImGui::SameLine();
if (WIDGET_FX(ImGui::Button(strings.get(Strings::ArcadeStatsButton).c_str(), ImVec2(buttonWidth, 0))))
view = SKILL_CHECK_STATS;
}
else if (view == SKILL_CHECK_STATS)
{
auto& schema = character.data.skillCheckSchema;
ImGui::PushFont(ImGui::GetFont(), resource::Font::HEADER_2);
ImGui::TextUnformatted(strings.get(Strings::ArcadeSkillCheckName).c_str());
ImGui::PopFont();
ImGui::Separator();
ImGui::Text(strings.get(Strings::ArcadeBestFormat).c_str(), skillCheck.highScore, skillCheck.bestCombo);
ImGui::Text(strings.get(Strings::ArcadeTotalSkillChecksFormat).c_str(), skillCheck.totalPlays);
for (int i = 0; i < (int)schema.grades.size(); i++)
{
auto& grade = schema.grades[i];
ImGui::Text("%s: %i", grade.namePlural.c_str(), skillCheck.gradeCounts[i]);
}
ImGui::Text(strings.get(Strings::ArcadeAccuracyFormat).c_str(), skillCheck.accuracy_score_get(character));
}
}
ImGui::EndChild();
if (view == SKILL_CHECK_STATS)
{
if (WIDGET_FX(ImGui::Button(strings.get(Strings::ArcadeBackButton).c_str()))) view = MENU;
}
}
}

26
src/state/play/arcade.hpp Normal file
View File

@@ -0,0 +1,26 @@
#pragma once
#include "arcade/skill_check.hpp"
namespace game::state::play
{
class Arcade
{
public:
enum View
{
MENU,
SKILL_CHECK,
SKILL_CHECK_STATS
};
SkillCheck skillCheck{};
View view{MENU};
Arcade() = default;
Arcade(entity::Character&);
void tick();
void update(Resources&, entity::Character&, Inventory&, Text&);
};
}

View File

@@ -6,13 +6,16 @@
#include "../../../util/imgui/widget.hpp"
#include "../../../util/math.hpp"
#include <array>
#include <cmath>
#include <cstdio>
#include <format>
#include <ranges>
using namespace game::util;
using namespace game::entity;
using namespace game::resource;
using namespace game::resource::xml;
using namespace glm;
namespace game::state::play
@@ -69,7 +72,7 @@ namespace game::state::play
actor.tick();
}
void SkillCheck::update(Resources& resources, entity::Character& character, Inventory& inventory, Text& text)
bool 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);
@@ -82,25 +85,31 @@ namespace game::state::play
auto& dialogue = character.data.dialogue;
auto& schema = character.data.skillCheckSchema;
auto& itemSchema = character.data.itemSchema;
auto& strings = character.data.strings;
auto& style = ImGui::GetStyle();
auto drawList = ImGui::GetWindowDrawList();
auto position = ImGui::GetCursorScreenPos();
auto size = ImGui::GetContentRegionAvail();
auto spacing = ImGui::GetTextLineHeightWithSpacing();
auto& io = ImGui::GetIO();
auto menuButtonHeight = ImGui::GetFrameHeightWithSpacing();
size.y = std::max(0.0f, size.y - menuButtonHeight);
auto cursorPos = ImGui::GetCursorPos();
ImGui::Text("Score: %i pts (%ix)", score, combo);
auto bestString = std::format("Best: {} pts({}x)", highScore, bestCombo);
ImGui::Text(strings.get(Strings::SkillCheckScoreFormat).c_str(), score, combo);
std::array<char, 128> bestBuffer{};
std::snprintf(bestBuffer.data(), bestBuffer.size(), strings.get(Strings::SkillCheckBestFormat).c_str(), highScore,
bestCombo);
auto bestString = std::string(bestBuffer.data());
ImGui::SetCursorPos(ImVec2(size.x - ImGui::CalcTextSize(bestString.c_str()).x, cursorPos.y));
ImGui::Text("Best: %i pts (%ix)", highScore, bestCombo);
ImGui::Text(strings.get(Strings::SkillCheckBestFormat).c_str(), highScore, bestCombo);
if (score == 0 && isActive)
{
ImGui::SetCursorPos(ImVec2(style.WindowPadding.x, size.y - style.WindowPadding.y));
ImGui::TextWrapped("Match the line to the colored areas with Space/click! Better performance, better rewards!");
ImGui::TextWrapped("%s", strings.get(Strings::SkillCheckInstructions).c_str());
}
auto barMin = ImVec2(position.x + (size.x * 0.5f) - (spacing * 0.5f), position.y + (spacing * 2.0f));
@@ -193,8 +202,11 @@ namespace game::state::play
score--;
schema.sounds.scoreLoss.play();
auto toastMessagePosition =
ImVec2(barMin.x - ImGui::CalcTextSize("-1").x - ImGui::GetTextLineHeightWithSpacing(), lineMin.y);
toasts.emplace_back("-1", toastMessagePosition, schema.endTimerMax, schema.endTimerMax);
ImVec2(barMin.x - ImGui::CalcTextSize(strings.get(Strings::SkillCheckScoreLoss).c_str()).x -
ImGui::GetTextLineHeightWithSpacing(),
lineMin.y);
toasts.emplace_back(strings.get(Strings::SkillCheckScoreLoss), toastMessagePosition, schema.endTimerMax,
schema.endTimerMax);
}
}
@@ -258,10 +270,10 @@ namespace game::state::play
}
auto toastMessagePosition =
ImVec2(barMin.x - ImGui::CalcTextSize("Fantastic score!\nCongratulations!").x -
ImVec2(barMin.x - ImGui::CalcTextSize(strings.get(Strings::SkillCheckRewardToast).c_str()).x -
ImGui::GetTextLineHeightWithSpacing(),
lineMin.y + (ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().ItemSpacing.y));
toasts.emplace_back("Fantastic score! Congratulations!", toastMessagePosition, schema.endTimerMax,
toasts.emplace_back(strings.get(Strings::SkillCheckRewardToast), toastMessagePosition, schema.endTimerMax,
schema.endTimerMax);
}
@@ -274,9 +286,11 @@ namespace game::state::play
isHighScoreAchievedThisRun = true;
schema.sounds.highScore.play();
auto toastMessagePosition =
ImVec2(barMin.x - ImGui::CalcTextSize("High Score!").x - ImGui::GetTextLineHeightWithSpacing(),
ImVec2(barMin.x - ImGui::CalcTextSize(strings.get(Strings::SkillCheckHighScoreToast).c_str()).x -
ImGui::GetTextLineHeightWithSpacing(),
lineMin.y + ImGui::GetTextLineHeightWithSpacing());
toasts.emplace_back("High Score!", toastMessagePosition, schema.endTimerMax, schema.endTimerMax);
toasts.emplace_back(strings.get(Strings::SkillCheckHighScoreToast), toastMessagePosition,
schema.endTimerMax, schema.endTimerMax);
}
}
@@ -337,10 +351,10 @@ namespace game::state::play
{
score = 0;
combo = 0;
if (isHighScoreAchieved) schema.sounds.highScoreLoss.play();
if (isHighScoreAchievedThisRun) schema.sounds.highScoreLoss.play();
if (highScore > 0) isHighScoreAchieved = true;
isRewardScoreAchieved = false;
isHighScoreAchievedThisRun = true;
isHighScoreAchievedThisRun = false;
highScoreStart = highScore;
isGameOver = true;
}
@@ -351,7 +365,9 @@ namespace game::state::play
queuedChallenge = challenge_generate(character);
auto string = grade.isFailure ? grade.name : std::format("{} (+{})", grade.name, grade.value);
auto string = grade.isFailure ? grade.name
: std::vformat(strings.get(Strings::SkillCheckGradeSuccessTemplate),
std::make_format_args(grade.name, grade.value));
auto toastMessagePosition =
ImVec2(barMin.x - ImGui::CalcTextSize(string.c_str()).x - ImGui::GetTextLineHeightWithSpacing(), lineMin.y);
toasts.emplace_back(string, toastMessagePosition, endTimerMax, endTimerMax);
@@ -429,5 +445,8 @@ namespace game::state::play
if (fallingItem.position.y > position.y + size.y) items.erase(items.begin() + i--);
}
ImGui::PopClipRect();
ImGui::SetCursorScreenPos(ImVec2(position.x, position.y + size.y + ImGui::GetStyle().ItemSpacing.y));
return WIDGET_FX(ImGui::Button(strings.get(Strings::SkillCheckMenuButton).c_str()));
}
}

View File

@@ -81,7 +81,7 @@ namespace game::state::play
SkillCheck(entity::Character&);
Challenge challenge_generate(entity::Character&);
void tick();
void update(Resources&, entity::Character&, Inventory&, Text&);
bool update(Resources&, entity::Character&, Inventory&, Text&);
float accuracy_score_get(entity::Character&);
};
}

View File

@@ -89,14 +89,18 @@ namespace game::state::play
interact_area_override_tick, interactArea.scaleEffectCycles));
}
if (interactArea.pool.is_valid() && text.is_interruptible())
text.set(dialogue.get(interactArea.pool), character);
if (text.is_interruptible())
{
auto& pool = character.is_over_capacity() && interactArea.poolFull.is_valid() ? interactArea.poolFull
: interactArea.pool;
if (pool.is_valid())
text.set(dialogue.get(pool), character);
}
}
if (isInteracting)
{
cursor.state = entity::Cursor::ACTION;
character.queue_interact_area_animation(interactArea);
cursor.queue_play({interactArea.animationCursorActive});
if (interactArea.digestionBonusRub > 0 && character.calories > 0 && !character.isDigesting)

View File

@@ -1,32 +0,0 @@
#include "chat.hpp"
#include "../../util/imgui/widget.hpp"
using namespace game::resource;
using namespace game::util::imgui;
namespace game::state::play
{
void Chat::update(Resources&, Text& text, entity::Character& character)
{
auto& dialogue = character.data.dialogue;
auto size = ImGui::GetContentRegionAvail();
ImGui::PushFont(ImGui::GetFont(), Font::HEADER_2);
if (dialogue.random.is_valid())
if (WIDGET_FX(ImGui::Button("Let's chat!", ImVec2(size.x, 0))))
text.set(dialogue.get(dialogue.random), character);
ImGui::PopFont();
if (dialogue.help.is_valid())
if (WIDGET_FX(ImGui::Button("Help", ImVec2(size.x, 0)))) text.set(dialogue.get(dialogue.help), character);
auto stage = glm::clamp(0, character.stage_get(), character.stage_max_get());
auto& pool = stage > 0 ? character.data.stages.at(stage - 1).pool : character.data.pool;
if (pool.is_valid())
if (WIDGET_FX(ImGui::Button("How are you feeling?", ImVec2(size.x, 0)))) text.set(dialogue.get(pool), character);
}
}

View File

@@ -8,82 +8,50 @@
using namespace game::util::imgui;
using namespace game::util;
using namespace game::resource::xml;
namespace game::state::play
{
void Cheats::update(Resources&, entity::Character& character, Inventory& inventory, Text& text)
void Cheats::update(Resources&, entity::Character& character, Inventory& inventory)
{
static constexpr auto FEED_INCREMENT = 100.0f;
auto& strings = character.data.strings;
if (ImGui::BeginChild("##Cheats"))
{
if (WIDGET_FX(ImGui::Button("Feed")))
{
character.calories = std::min(character.calories + FEED_INCREMENT, character.max_capacity());
character.queue_idle_animation();
}
ImGui::SameLine();
if (WIDGET_FX(ImGui::Button("Starve")))
{
character.calories = std::max(0.0f, character.calories - FEED_INCREMENT);
character.queue_idle_animation();
}
ImGui::SameLine();
if (WIDGET_FX(ImGui::Button("Digest"))) character.digestionProgress = entity::Character::DIGESTION_MAX;
auto stage = character.stage + 1;
if (WIDGET_FX(ImGui::SliderInt("Stage", &stage, 1, (int)character.data.stages.size() + 1)))
auto weight_update = [&]() { character.queue_idle_animation(); };
WIDGET_FX(ImGui::SliderFloat(strings.get(Strings::CheatsCalories).c_str(), &character.calories, 0,
character.max_capacity(), "%0.0f kcal"));
WIDGET_FX(ImGui::SliderFloat(strings.get(Strings::CheatsCapacity).c_str(), &character.capacity,
character.data.capacityMin, character.data.capacityMax, "%0.0f kcal"));
if (WIDGET_FX(ImGui::SliderFloat(strings.get(Strings::CheatsWeight).c_str(), &character.weight,
character.data.weight, character.data.weightMax,
strings.get(Strings::CheatsWeightFormat).c_str())))
weight_update();
if (WIDGET_FX(ImGui::SliderInt(strings.get(Strings::CheatsStage).c_str(), &stage, 1,
(int)character.data.stages.size() + 1)))
{
character.stage = glm::clamp(0, stage - 1, (int)character.data.stages.size());
character.weight =
character.stage == 0 ? character.data.weight : character.data.stages.at(character.stage - 1).threshold;
character.queue_idle_animation();
weight_update();
}
WIDGET_FX(ImGui::SliderFloat("Capacity", &character.capacity, character.data.capacityMin,
character.data.capacityMax, "%0.0f kcal"));
WIDGET_FX(ImGui::SliderFloat(strings.get(Strings::CheatsDigestionRate).c_str(), &character.digestionRate,
character.data.digestionRateMin, character.data.digestionRateMax,
strings.get(Strings::CheatsDigestionRateFormat).c_str()));
WIDGET_FX(ImGui::SliderFloat(strings.get(Strings::CheatsEatSpeed).c_str(), &character.eatSpeed,
character.data.eatSpeedMin, character.data.eatSpeedMax,
strings.get(Strings::CheatsEatSpeedFormat).c_str()));
WIDGET_FX(ImGui::SliderFloat("Digestion Rate", &character.digestionRate, character.data.digestionRateMin,
character.data.digestionRateMax, "%0.2f% / tick"));
WIDGET_FX(ImGui::SliderFloat("Eat Speed", &character.eatSpeed, character.data.eatSpeedMin,
character.data.eatSpeedMax, "%0.2fx"));
if (WIDGET_FX(ImGui::Button(strings.get(Strings::CheatsDigestButton).c_str())))
character.digestionProgress = entity::Character::DIGESTION_MAX;
ImGui::SeparatorText("Animations");
ImGui::Text("Now Playing: %s", character.animationMapReverse.at(character.animationIndex).c_str());
auto childSize = ImVec2(0, ImGui::GetContentRegionAvail().y / 3);
if (ImGui::BeginChild("##Animations", childSize, ImGuiChildFlags_Borders))
{
for (int i = 0; i < (int)character.animations.size(); i++)
{
auto& animation = character.animations[i];
ImGui::PushID(i);
if (WIDGET_FX(ImGui::Selectable(animation.name.c_str())))
character.play(animation.name.c_str(), entity::Actor::PLAY_FORCE);
ImGui::SetItemTooltip("%s", animation.name.c_str());
ImGui::PopID();
}
}
ImGui::EndChild();
ImGui::SeparatorText("Dialogue");
if (ImGui::BeginChild("##Dialogue", childSize, ImGuiChildFlags_Borders))
{
for (int i = 0; i < (int)character.data.dialogue.entries.size(); i++)
{
auto& entry = character.data.dialogue.entries[i];
ImGui::PushID(i);
if (WIDGET_FX(ImGui::Selectable(entry.name.c_str()))) text.set(&entry, character);
ImGui::SetItemTooltip("%s", entry.name.c_str());
ImGui::PopID();
}
}
ImGui::EndChild();
ImGui::SeparatorText("Inventory");
ImGui::SeparatorText(strings.get(Strings::CheatsInventory).c_str());
if (ImGui::BeginChild("##Inventory", ImGui::GetContentRegionAvail(), ImGuiChildFlags_Borders))
{

View File

@@ -10,7 +10,6 @@ namespace game::state::play
class Cheats
{
public:
void update(Resources&, entity::Character&, Inventory&, Text&);
void update(Resources&, entity::Character&, Inventory&);
};
}

View File

@@ -5,31 +5,68 @@
#include <ranges>
using namespace game::util::imgui;
using namespace game::resource::xml;
namespace game::state::play
{
void Debug::update(entity::Character& character, entity::Cursor& cursor, ItemManager& itemManager, Canvas& canvas)
void Debug::update(entity::Character& character, entity::Cursor& cursor, ItemManager& itemManager, Canvas& canvas,
Text& text)
{
auto& strings = character.data.strings;
auto cursorPosition = canvas.screen_position_convert(cursor.position);
ImGui::Text("Cursor Pos (Screen): %0.0f, %0.0f", cursor.position.x, cursor.position.y);
ImGui::Text("Cursor Pos (World): %0.0f, %0.0f", cursorPosition.x, cursorPosition.y);
ImGui::Text(strings.get(Strings::DebugCursorScreenFormat).c_str(), cursor.position.x, cursor.position.y);
ImGui::Text(strings.get(Strings::DebugCursorWorldFormat).c_str(), cursorPosition.x, cursorPosition.y);
WIDGET_FX(ImGui::Checkbox("Show Nulls (Hitboxes)", &character.isShowNulls));
WIDGET_FX(ImGui::Checkbox("Show World Bounds", &isBoundsDisplay));
ImGui::SeparatorText(strings.get(Strings::DebugAnimations).c_str());
ImGui::Text(strings.get(Strings::DebugNowPlayingFormat).c_str(), character.animationMapReverse.at(character.animationIndex).c_str());
auto childSize = ImVec2(0, ImGui::GetContentRegionAvail().y / 3);
if (ImGui::BeginChild("##Animations", childSize, ImGuiChildFlags_Borders))
{
for (int i = 0; i < (int)character.animations.size(); i++)
{
auto& animation = character.animations[i];
ImGui::PushID(i);
if (WIDGET_FX(ImGui::Selectable(animation.name.c_str())))
character.play(animation.name.c_str(), entity::Actor::PLAY_FORCE);
ImGui::SetItemTooltip("%s", animation.name.c_str());
ImGui::PopID();
}
}
ImGui::EndChild();
ImGui::SeparatorText(strings.get(Strings::DebugDialogue).c_str());
if (ImGui::BeginChild("##Dialogue", childSize, ImGuiChildFlags_Borders))
{
for (int i = 0; i < (int)character.data.dialogue.entries.size(); i++)
{
auto& entry = character.data.dialogue.entries[i];
ImGui::PushID(i);
if (WIDGET_FX(ImGui::Selectable(entry.name.c_str()))) text.set(&entry, character);
ImGui::SetItemTooltip("%s", entry.name.c_str());
ImGui::PopID();
}
}
ImGui::EndChild();
WIDGET_FX(ImGui::Checkbox(strings.get(Strings::DebugShowNulls).c_str(), &character.isShowNulls));
WIDGET_FX(ImGui::Checkbox(strings.get(Strings::DebugShowWorldBounds).c_str(), &isBoundsDisplay));
if (!itemManager.items.empty())
{
ImGui::SeparatorText("Item");
ImGui::SeparatorText(strings.get(Strings::DebugItem).c_str());
for (int i = 0; i < (int)itemManager.items.size(); i++)
{
auto& item = itemManager.items[i];
if (itemManager.heldItemIndex == i) ImGui::Text("Held");
ImGui::Text("Type: %i", item.schemaID);
ImGui::Text("Position: %0.0f, %0.0f", item.position.x, item.position.y);
ImGui::Text("Velocity: %0.0f, %0.0f", item.velocity.x, item.velocity.y);
ImGui::Text("Chew Count: %i", item.chewCount);
if (itemManager.heldItemIndex == i) ImGui::TextUnformatted(strings.get(Strings::DebugHeld).c_str());
ImGui::Text(strings.get(Strings::DebugItemTypeFormat).c_str(), item.schemaID);
ImGui::Text(strings.get(Strings::DebugItemPositionFormat).c_str(), item.position.x, item.position.y);
ImGui::Text(strings.get(Strings::DebugItemVelocityFormat).c_str(), item.velocity.x, item.velocity.y);
ImGui::Text(strings.get(Strings::DebugItemDurabilityFormat).c_str(), item.durability);
ImGui::Separator();
}
}

View File

@@ -4,6 +4,7 @@
#include "../../entity/cursor.hpp"
#include "item_manager.hpp"
#include "text.hpp"
#include <imgui.h>
@@ -14,6 +15,6 @@ namespace game::state::play
public:
bool isBoundsDisplay{};
void update(entity::Character&, entity::Cursor& cursor, ItemManager&, Canvas& canvas);
void update(entity::Character&, entity::Cursor&, ItemManager&, Canvas&, Text&);
};
}

View File

@@ -9,6 +9,7 @@
#include <format>
using namespace game::resource;
using namespace game::resource::xml;
using namespace game::util;
namespace game::state::play
@@ -18,6 +19,7 @@ namespace game::state::play
static constexpr auto WIDTH_MULTIPLIER = 0.30f;
static constexpr auto HEIGHT_MULTIPLIER = 4.0f;
auto& strings = character.data.strings;
auto& style = ImGui::GetStyle();
auto windowSize = imgui::to_ivec2(ImGui::GetMainViewport()->Size);
@@ -45,26 +47,29 @@ namespace game::state::play
auto unitString = (system == measurement::IMPERIAL ? "lbs" : "kg");
auto weightString = util::string::format_commas(weight, 2) + " " + unitString;
ImGui::PushFont(ImGui::GetFont(), Font::ABOVE_AVERAGE);
ImGui::PushFont(ImGui::GetFont(), Font::HEADER_1);
ImGui::TextUnformatted(weightString.c_str());
ImGui::SetItemTooltip("%s", weightString.c_str());
ImGui::PopFont();
auto stageProgress = character.stage_progress_get();
ImGui::ProgressBar(stageProgress, ImVec2(ImGui::GetContentRegionAvail().x, 0),
stage >= stageMax ? "MAX" : "To Next Stage");
strings.get(stage >= stageMax ? Strings::InfoProgressMax
: Strings::InfoProgressToNextStage)
.c_str());
if (ImGui::BeginItemTooltip())
{
ImGui::Text("Stage: %i/%i (%0.1f%%)", stage + 1, stageMax + 1, math::to_percent(stageProgress));
ImGui::Text(strings.get(Strings::InfoStageProgressFormat).c_str(), stage + 1, stageMax + 1,
math::to_percent(stageProgress));
ImGui::Separator();
ImGui::PushStyleColor(ImGuiCol_Text, imgui::to_imvec4(color::GRAY));
if (stage >= stageMax)
ImGui::Text("Maxed out!");
ImGui::TextUnformatted(strings.get(Strings::InfoMaxedOut).c_str());
else
{
ImGui::Text("Start: %0.2f %s", stageWeight, unitString);
ImGui::Text("Current: %0.2f %s", weight, unitString);
ImGui::Text("Next: %0.2f %s", stageNextWeight, unitString);
ImGui::Text(strings.get(Strings::InfoStageStartFormat).c_str(), stageWeight, unitString);
ImGui::Text(strings.get(Strings::InfoStageCurrentFormat).c_str(), weight, unitString);
ImGui::Text(strings.get(Strings::InfoStageNextFormat).c_str(), stageNextWeight, unitString);
}
ImGui::PopStyleColor();
ImGui::EndTooltip();
@@ -82,7 +87,7 @@ namespace game::state::play
auto overstuffedPercent = std::max(0.0f, (calories - capacity) / (character.max_capacity() - capacity));
auto caloriesColor = ImVec4(1.0f, 1.0f - overstuffedPercent, 1.0f - overstuffedPercent, 1.0f);
ImGui::PushFont(ImGui::GetFont(), Font::ABOVE_AVERAGE);
ImGui::PushFont(ImGui::GetFont(), Font::HEADER_1);
ImGui::PushStyleColor(ImGuiCol_Text, caloriesColor);
auto caloriesString = std::format("{:.0f} kcal / {:.0f} kcal", calories,
character.is_over_capacity() ? character.max_capacity() : character.capacity);
@@ -95,14 +100,16 @@ namespace game::state::play
? (float)character.digestionTimer / character.data.digestionTimerMax
: character.digestionProgress / entity::Character::DIGESTION_MAX;
ImGui::ProgressBar(digestionProgress, ImVec2(ImGui::GetContentRegionAvail().x, 0),
character.isDigesting ? "Digesting..." : "Digestion");
strings.get(character.isDigesting ? Strings::InfoDigesting
: Strings::InfoDigestion)
.c_str());
if (ImGui::BeginItemTooltip())
{
if (character.isDigesting)
ImGui::TextUnformatted("Digestion in progress...");
ImGui::TextUnformatted(strings.get(Strings::InfoDigestionInProgress).c_str());
else if (digestionProgress <= 0.0f)
ImGui::TextUnformatted("Give food to start digesting!");
ImGui::TextUnformatted(strings.get(Strings::InfoGiveFoodToStartDigesting).c_str());
else
ImGui::Text("%0.2f%%", math::to_percent(digestionProgress));
@@ -110,8 +117,8 @@ namespace game::state::play
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(imgui::to_imvec4(color::GRAY)));
ImGui::Text("Rate: %0.2f%% / sec", character.digestion_rate_get());
ImGui::Text("Eating Speed: %0.2fx", character.eatSpeed);
ImGui::Text(strings.get(Strings::InfoDigestionRateFormat).c_str(), character.digestion_rate_get());
ImGui::Text(strings.get(Strings::InfoEatingSpeedFormat).c_str(), character.eatSpeed);
ImGui::PopStyleColor();

View File

@@ -0,0 +1,57 @@
#include "interact.hpp"
#include "../../util/imgui/widget.hpp"
#include "../../util/measurement.hpp"
using namespace game::resource;
using namespace game::resource::xml;
using namespace game::util;
using namespace game::util::imgui;
namespace game::state::play
{
void Interact::update(Resources& resources, Text& text, entity::Character& character)
{
auto& dialogue = character.data.dialogue;
auto& strings = character.data.strings;
auto size = ImGui::GetContentRegionAvail();
ImGui::PushFont(ImGui::GetFont(), resource::Font::HEADER_2);
if (dialogue.random.is_valid())
if (WIDGET_FX(ImGui::Button(strings.get(Strings::InteractChatButton).c_str(), ImVec2(size.x, 0))))
text.set(dialogue.get(dialogue.random), character);
ImGui::PopFont();
if (dialogue.help.is_valid())
if (WIDGET_FX(ImGui::Button(strings.get(Strings::InteractHelpButton).c_str(), ImVec2(size.x, 0))))
text.set(dialogue.get(dialogue.help), character);
auto stage = glm::clamp(0, character.stage_get(), character.stage_max_get());
auto& pool = stage > 0 ? character.data.stages.at(stage - 1).pool : character.data.pool;
if (pool.is_valid())
if (WIDGET_FX(
ImGui::Button(strings.get(Strings::InteractFeelingButton).c_str(), ImVec2(size.x, 0))))
text.set(dialogue.get(pool), character);
ImGui::PushFont(ImGui::GetFont(), resource::Font::HEADER_1);
ImGui::SeparatorText(character.data.name.c_str());
ImGui::PopFont();
auto& system = resources.settings.measurementSystem;
auto weight = character.weight_get(system);
auto weightUnit = system == measurement::IMPERIAL ? "lbs" : "kg";
ImGui::Text(strings.get(Strings::InteractWeightFormat).c_str(), weight, weightUnit,
character.stage_get() + 1);
ImGui::Text(strings.get(Strings::InteractCapacityFormat).c_str(), character.capacity,
character.max_capacity());
ImGui::Text(strings.get(Strings::InteractDigestionRateFormat).c_str(), character.digestion_rate_get());
ImGui::Text(strings.get(Strings::InteractEatingSpeedFormat).c_str(), character.eatSpeed);
ImGui::Separator();
ImGui::Text(strings.get(Strings::InteractTotalCaloriesFormat).c_str(), character.totalCaloriesConsumed);
ImGui::Text(strings.get(Strings::InteractTotalFoodItemsFormat).c_str(), character.totalFoodItemsEaten);
}
}

View File

@@ -6,7 +6,7 @@
namespace game::state::play
{
class Chat
class Interact
{
public:
void update(Resources&, Text&, entity::Character&);

View File

@@ -1,4 +1,5 @@
#include "inventory.hpp"
#include "style.hpp"
#include <cmath>
#include <format>
@@ -7,6 +8,7 @@
#include "../../util/color.hpp"
#include "../../util/imgui.hpp"
#include "../../util/imgui/style.hpp"
#include "../../util/imgui/widget.hpp"
#include "../../util/math.hpp"
@@ -18,6 +20,8 @@ using namespace glm;
namespace game::state::play
{
using Strings = resource::xml::Strings;
void Inventory::tick()
{
for (auto& [i, actor] : actors)
@@ -29,6 +33,7 @@ namespace game::state::play
static constexpr auto INFO_CHILD_HEIGHT_MULTIPLIER = 1.0f / 3.0f;
auto& schema = character.data.itemSchema;
auto& strings = character.data.strings;
auto quantity_get = [&](int itemID) -> int&
{
@@ -46,6 +51,77 @@ namespace game::state::play
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_summary_draw = [&](const resource::xml::Item::Entry& item, int quantity)
{
auto& category = schema.categories[item.categoryID];
auto& rarity = schema.rarities[item.rarityID];
auto durability = item.durability.value_or(schema.durability);
ImGui::PushFont(ImGui::GetFont(), Font::HEADER_2);
ImGui::TextWrapped("%s (x%i)", item.name.c_str(), quantity);
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(strings.get(Strings::InventoryFlavorFormat).c_str(),
schema.flavors[*item.flavorID].name.c_str());
if (item.calories.has_value())
ImGui::TextWrapped(strings.get(Strings::InventoryCaloriesFormat).c_str(), *item.calories);
ImGui::TextWrapped(strings.get(Strings::InventoryDurabilityFormat).c_str(), durability);
if (item.capacityBonus.has_value())
ImGui::TextWrapped(strings.get(Strings::InventoryCapacityBonusFormat).c_str(), *item.capacityBonus);
if (item.digestionBonus.has_value())
{
if (*item.digestionBonus > 0)
ImGui::TextWrapped(strings.get(Strings::InventoryDigestionRateBonusFormat).c_str(),
*item.digestionBonus * 60.0f);
else if (*item.digestionBonus < 0)
ImGui::TextWrapped(strings.get(Strings::InventoryDigestionRatePenaltyFormat).c_str(),
*item.digestionBonus * 60.0f);
}
if (item.eatSpeedBonus.has_value())
{
if (*item.eatSpeedBonus > 0)
ImGui::TextWrapped(strings.get(Strings::InventoryEatSpeedBonusFormat).c_str(), *item.eatSpeedBonus);
else if (*item.eatSpeedBonus < 0)
ImGui::TextWrapped(strings.get(Strings::InventoryEatSpeedPenaltyFormat).c_str(), *item.eatSpeedBonus);
}
if (is_possible_to_upgrade_get(item))
ImGui::TextWrapped(strings.get(Strings::InventoryUpgradePreviewFormat).c_str(), *item.upgradeCount,
schema.idToStringMap.at(*item.upgradeID).c_str());
ImGui::PopStyleColor();
ImGui::Separator();
};
auto item_details_draw = [&](const resource::xml::Item::Entry& item, int quantity)
{
item_summary_draw(item, quantity);
if (ImGui::BeginChild("##Info Description Child", ImGui::GetContentRegionAvail()))
ImGui::TextWrapped("%s", item.description.c_str());
ImGui::EndChild();
};
auto item_tooltip_draw = [&](const resource::xml::Item::Entry& item, int quantity)
{
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 24.0f);
item_summary_draw(item, quantity);
ImGui::TextWrapped("%s", item.description.c_str());
ImGui::PopTextWrapPos();
};
auto item_unknown_draw = [&]()
{
ImGui::PushFont(ImGui::GetFont(), Font::HEADER_2);
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 24.0f);
ImGui::TextWrapped("%s", strings.get(Strings::InventoryUnknown).c_str());
ImGui::PopTextWrapPos();
ImGui::PopFont();
};
auto item_use = [&](int itemID)
{
auto& item = schema.items[itemID];
@@ -176,6 +252,7 @@ namespace game::state::play
auto& item = schema.items[i];
auto& quantity = quantity_get(i);
auto& rarity = schema.rarities[item.rarityID];
auto hasItemColor = item.color.has_value();
if (rarity.isHidden && quantity <= 0) continue;
@@ -185,6 +262,7 @@ namespace game::state::play
auto cursorScreenPos = ImGui::GetCursorScreenPos();
auto [canvas, rect] = item_canvas_get(i, size);
auto isSelected = selectedItemID == i;
if (hasItemColor) imgui::style::color_set(*item.color);
if (isSelected)
{
@@ -201,8 +279,16 @@ namespace game::state::play
isAnyInventoryItemHovered = isAnyInventoryItemHovered || ImGui::IsItemHovered();
if (isPressed) selectedItemID = i;
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && quantity > 0) item_use(i);
if (ImGui::BeginItemTooltip())
{
if (quantity > 0)
item_tooltip_draw(item, quantity);
else
item_unknown_draw();
ImGui::EndTooltip();
}
ImGui::PushFont(ImGui::GetFont(), Font::BIG);
ImGui::PushFont(ImGui::GetFont(), Font::HEADER_2);
auto text = std::format("x{}", quantity);
auto textPos = ImVec2(cursorScreenPos.x + size.x - ImGui::CalcTextSize(text.c_str()).x,
@@ -210,6 +296,7 @@ namespace game::state::play
ImGui::GetWindowDrawList()->AddText(textPos, ImGui::GetColorU32(ImGui::GetStyleColorVec4(ImGuiCol_Text)),
text.c_str());
ImGui::PopFont();
if (hasItemColor) style::color_set(resources, character);
auto increment = ImGui::GetItemRectSize().x + ImGui::GetStyle().ItemSpacing.x;
cursorPos.x += increment;
@@ -231,13 +318,15 @@ namespace game::state::play
isItemSelected = selectedItemID >= 0 && selectedItemID < (int)schema.items.size();
auto selectedQuantity = isItemSelected ? quantity_get(selectedItemID) : 0;
auto isSelectedItemKnown = isItemSelected && selectedQuantity > 0;
auto selectedItemHasColor = isItemSelected && schema.items[selectedItemID].color.has_value();
if (isInfoVisible &&
ImGui::BeginChild("##Info Child", infoChildSize, ImGuiChildFlags_None, ImGuiWindowFlags_NoScrollbar))
{
if (selectedItemHasColor) imgui::style::color_set(*schema.items[selectedItemID].color);
ImGui::Separator();
auto isButtonChildVisible = selectedQuantity > 0;
ImGui::PushFont(resources.font.get(), Font::BIG);
ImGui::PushFont(resources.font.get(), Font::HEADER_2);
auto buttonRowHeight = ImGui::GetFrameHeight();
auto buttonChildHeight =
isButtonChildVisible ? buttonRowHeight * 2.0f + ImGui::GetStyle().ItemSpacing.y * 5.0f : 0.0f;
@@ -252,56 +341,18 @@ namespace game::state::play
{
if (!isItemSelected)
{
ImGui::PushFont(ImGui::GetFont(), Font::BIG);
ImGui::TextWrapped("%s", "Check the \"Arcade\" tab to earn rewards!");
ImGui::PushFont(ImGui::GetFont(), Font::HEADER_2);
ImGui::TextWrapped("%s", strings.get(Strings::InventoryEmptyHint).c_str());
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());
}
item_details_draw(item, selectedQuantity);
else
{
ImGui::PushFont(ImGui::GetFont(), Font::BIG);
ImGui::TextWrapped("%s", "???");
ImGui::PopFont();
}
item_unknown_draw();
}
}
ImGui::EndChild();
@@ -310,28 +361,75 @@ namespace game::state::play
ImGui::BeginChild("##Info Actions Child", buttonChildSize, ImGuiChildFlags_None,
ImGuiWindowFlags_NoScrollbar))
{
auto& selectedItem = schema.items[selectedItemID];
auto canUseSelectedItem = true;
auto canUpgradeSelectedItem = is_able_to_upgrade_get(schema.items[selectedItemID], selectedQuantity);
auto canUpgradeSelectedItem = is_able_to_upgrade_get(selectedItem, selectedQuantity);
auto rowTwoButtonSize = row_widget_size_get(2);
auto upgrade_item_name_get = [&]() -> std::string
{
if (!selectedItem.upgradeID.has_value()) return {};
return schema.items.at(*selectedItem.upgradeID).name;
};
auto upgrade_tooltip_get = [&](bool isAll)
{
if (!is_possible_to_upgrade_get(selectedItem))
return strings.get(Strings::InventoryUpgradeNoPath);
auto upgradeItemName = upgrade_item_name_get();
auto upgradeCount = *selectedItem.upgradeCount;
if (!canUpgradeSelectedItem)
return std::vformat(strings.get(Strings::InventoryUpgradeNeedsTemplate),
std::make_format_args(upgradeCount, upgradeItemName));
if (!isAll)
return std::vformat(strings.get(Strings::InventoryUpgradeOneTemplate),
std::make_format_args(upgradeCount, upgradeItemName));
auto upgradedCount = selectedQuantity / upgradeCount;
return std::vformat(strings.get(Strings::InventoryUpgradeAllTemplate),
std::make_format_args(upgradeCount, upgradedCount, upgradeItemName));
};
ImGui::Separator();
ImGui::Dummy(ImVec2(0, ImGui::GetStyle().ItemSpacing.y));
ImGui::PushFont(ImGui::GetFont(), Font::BIG);
ImGui::PushFont(ImGui::GetFont(), Font::HEADER_2);
ImGui::BeginDisabled(!canUseSelectedItem);
if (WIDGET_FX(ImGui::Button("Spawn", {ImGui::GetContentRegionAvail().x, 0}))) item_use(selectedItemID);
if (WIDGET_FX(ImGui::Button(strings.get(Strings::InventorySpawnButton).c_str(),
{ImGui::GetContentRegionAvail().x, 0})))
item_use(selectedItemID);
ImGui::EndDisabled();
ImGui::BeginDisabled(!canUpgradeSelectedItem);
if (WIDGET_FX(ImGui::Button("Upgrade", rowTwoButtonSize))) item_upgrade(selectedItemID, false);
if (WIDGET_FX(
ImGui::Button(strings.get(Strings::InventoryUpgradeButton).c_str(), rowTwoButtonSize)))
item_upgrade(selectedItemID, false);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
{
ImGui::PushFont(ImGui::GetFont(), Font::NORMAL);
ImGui::SetItemTooltip("%s", upgrade_tooltip_get(false).c_str());
ImGui::PopFont();
}
ImGui::SameLine();
if (WIDGET_FX(ImGui::Button("Upgrade All", rowTwoButtonSize))) item_upgrade(selectedItemID, true);
if (WIDGET_FX(ImGui::Button(strings.get(Strings::InventoryUpgradeAllButton).c_str(),
rowTwoButtonSize)))
item_upgrade(selectedItemID, true);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
{
ImGui::PushFont(ImGui::GetFont(), Font::NORMAL);
ImGui::SetItemTooltip("%s", upgrade_tooltip_get(true).c_str());
ImGui::PopFont();
}
ImGui::EndDisabled();
ImGui::PopFont();
}
if (isButtonChildVisible) ImGui::EndChild();
if (selectedItemHasColor) style::color_set(resources, character);
}
if (isInfoVisible) ImGui::EndChild();
}

View File

@@ -15,6 +15,18 @@ using namespace glm;
namespace game::state::play
{
namespace
{
int durability_animation_index_get(const resource::xml::Item& schema, const resource::xml::Anm2& anm2, int durability,
int durabilityMax)
{
if (durability >= durabilityMax) return -1;
auto animationName = schema.animations.chew + std::to_string(std::max(0, durability));
return anm2.animationMap.contains(animationName) ? anm2.animationMap.at(animationName) : -1;
}
}
void ItemManager::update(entity::Character& character, entity::Cursor& cursor, AreaManager& areaManager, Text& text,
const glm::vec4& bounds, Canvas& canvas)
{
@@ -70,7 +82,11 @@ namespace game::state::play
math::random_in_range(spawnBounds.y, spawnBounds.y + spawnBounds.w));
auto& itemSchema = character.data.itemSchema;
items.emplace_back(itemSchema.anm2s.at(id), position, id);
auto& item = itemSchema.items.at(id);
auto& anm2 = itemSchema.anm2s.at(id);
auto durabilityMax = item.durability.value_or(itemSchema.durability);
auto animationIndex = durability_animation_index_get(itemSchema, anm2, 0, durabilityMax);
items.emplace_back(anm2, position, id, 0, animationIndex);
}
queuedItemIDs.clear();
@@ -97,15 +113,15 @@ namespace game::state::play
if (schema.categories[item.categoryID].isEdible)
{
auto& chewCountMax = item.chewCount.has_value() ? *item.chewCount : schema.chewCount;
auto caloriesChew = item.calories.has_value() ? *item.calories / (chewCountMax + 1) : 0;
auto isCanEat = character.calories + caloriesChew <= character.max_capacity();
auto& durabilityMax = item.durability.has_value() ? *item.durability : schema.durability;
auto caloriesPerBite = item.calories.has_value() && durabilityMax > 0 ? *item.calories / durabilityMax : 0;
auto isCanEat = character.calories + caloriesPerBite <= character.max_capacity();
if (isJustItemHeld)
{
if (isCanEat)
text.set(dialogue.get(isOverCapacity ? dialogue.feedFull : dialogue.feed), character);
else if (caloriesChew > character.capacity)
else if (caloriesPerBite > character.capacity)
text.set(dialogue.get(dialogue.lowCapacity), character);
else
text.set(dialogue.get(dialogue.full), character);
@@ -125,37 +141,44 @@ namespace game::state::play
if (character.playedEventID == eatArea.eventID)
{
heldItem->chewCount++;
heldItem->durability++;
character.consume_played_event();
auto chewAnimation = schema.animations.chew + std::to_string(heldItem->chewCount);
auto animationIndex = heldItem->chewCount > 0 ? heldItem->animationMap[chewAnimation] : -1;
heldItem->play(animationIndex, entity::Actor::SET);
character.calories += caloriesChew;
character.totalCaloriesConsumed += caloriesChew;
character.calories += caloriesPerBite;
character.totalCaloriesConsumed += caloriesPerBite;
if (item.capacityBonus.has_value())
{
character.capacity += *item.capacityBonus / durabilityMax;
character.capacity =
glm::clamp(character.capacity, (float)character.data.capacityMin, (float)character.data.capacityMax);
}
if (item.eatSpeedBonus.has_value())
{
character.eatSpeed += *item.eatSpeedBonus / (chewCountMax + 1);
character.eatSpeed =
glm::clamp(character.data.eatSpeedMin, character.eatSpeed, character.data.eatSpeedMax);
character.eatSpeed += *item.eatSpeedBonus / durabilityMax;
character.eatSpeed = glm::clamp(character.eatSpeed, (float)character.data.eatSpeedMin,
(float)character.data.eatSpeedMax);
}
if (item.digestionBonus.has_value())
{
character.digestionRate += *item.digestionBonus / (chewCountMax + 1);
character.digestionRate = glm::clamp(character.data.digestionRateMin, character.digestionRate,
character.data.digestionRateMax);
character.digestionRate += *item.digestionBonus / durabilityMax;
character.digestionRate = glm::clamp(character.digestionRate, (float)character.data.digestionRateMin,
(float)character.data.digestionRateMax);
}
if (heldItem->chewCount > chewCountMax)
if (heldItem->durability >= durabilityMax)
{
isQueueFinishFood = true;
character.totalFoodItemsEaten++;
queuedRemoveItemIndex = heldItemIndex;
heldItemIndex = -1;
}
else
{
auto animationIndex =
durability_animation_index_get(schema, *heldItem, heldItem->durability, durabilityMax);
heldItem->play(animationIndex, entity::Actor::SET);
}
}
}
@@ -177,7 +200,7 @@ namespace game::state::play
// Food stolen
if (auto animation = character.animation_get(character.animation_name_convert(eatArea.animation));
character.is_playing(animation->name))
animation && character.is_playing(animation->name))
{
if (!math::is_point_in_rectf(rect, heldItem->position))
text.set(dialogue.get(isOverCapacity ? dialogue.foodTakenFull : dialogue.foodTaken), character);
@@ -232,7 +255,7 @@ namespace game::state::play
if (isMouseRightClicked)
{
if (item.chewCount > 0)
if (item.durability > 0)
schema.sounds.dispose.play();
else
{

View File

@@ -1,5 +1,7 @@
#include "menu.hpp"
#include "style.hpp"
#include "../../util/imgui.hpp"
#include "../../util/imgui/style.hpp"
#include "../../util/imgui/widget.hpp"
@@ -8,18 +10,14 @@
using namespace game::util;
using namespace game::util::imgui;
using namespace game::resource::xml;
namespace game::state::play
{
void Menu::tick()
{
inventory.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);
arcade.tick();
}
void Menu::update(Resources& resources, ItemManager& itemManager, entity::Character& character,
@@ -28,6 +26,7 @@ namespace game::state::play
static constexpr auto WIDTH_MULTIPLIER = 0.30f;
auto& schema = character.data.menuSchema;
auto& strings = character.data.strings;
auto style = ImGui::GetStyle();
auto& io = ImGui::GetIO();
@@ -61,47 +60,41 @@ namespace game::state::play
if (ImGui::BeginTabBar("##Options"))
{
if (isChat && WIDGET_FX(ImGui::BeginTabItem("Chat")))
if (WIDGET_FX(ImGui::BeginTabItem(strings.get(Strings::MenuTabInteract).c_str())))
{
chat.update(resources, text, character);
interact.update(resources, text, character);
ImGui::EndTabItem();
}
if (WIDGET_FX(ImGui::BeginTabItem("Arcade")))
if (WIDGET_FX(ImGui::BeginTabItem(strings.get(Strings::MenuTabArcade).c_str())))
{
skillCheck.update(resources, character, inventory, text);
arcade.update(resources, character, inventory, text);
ImGui::EndTabItem();
}
if (WIDGET_FX(ImGui::BeginTabItem("Inventory")))
if (WIDGET_FX(ImGui::BeginTabItem(strings.get(Strings::MenuTabInventory).c_str())))
{
inventory.update(resources, itemManager, character);
ImGui::EndTabItem();
}
if (WIDGET_FX(ImGui::BeginTabItem("Stats")))
if (WIDGET_FX(ImGui::BeginTabItem(strings.get(Strings::MenuTabSettings).c_str())))
{
stats.update(resources, skillCheck, character);
settingsMenu.update(resources, SettingsMenu::PLAY, &strings);
if (settingsMenu.isJustColorSet) style::color_set(resources, character);
ImGui::EndTabItem();
}
if (WIDGET_FX(ImGui::BeginTabItem("Settings")))
if (isCheats && WIDGET_FX(ImGui::BeginTabItem(strings.get(Strings::MenuTabCheats).c_str())))
{
settingsMenu.update(resources, SettingsMenu::PLAY);
if (settingsMenu.isJustColorSet) color_set_check(resources, character);
ImGui::EndTabItem();
}
if (isCheats && WIDGET_FX(ImGui::BeginTabItem("Cheats")))
{
cheats.update(resources, character, inventory, text);
cheats.update(resources, character, inventory);
ImGui::EndTabItem();
}
#if DEBUG
if (WIDGET_FX(ImGui::BeginTabItem("Debug")))
if (WIDGET_FX(ImGui::BeginTabItem(strings.get(Strings::MenuTabDebug).c_str())))
{
debug.update(character, cursor, itemManager, canvas);
debug.update(character, cursor, itemManager, canvas, text);
ImGui::EndTabItem();
}
#endif
@@ -128,7 +121,9 @@ namespace game::state::play
if (t <= 0.0f || t >= 1.0f)
{
ImGui::SetItemTooltip(isOpen ? "Close Main Menu" : "Open Main Menu");
ImGui::SetItemTooltip("%s", strings.get(isOpen ? Strings::MenuCloseTooltip
: Strings::MenuOpenTooltip)
.c_str());
if (result)
{
isOpen = !isOpen;

View File

@@ -4,11 +4,11 @@
#include "../settings_menu.hpp"
#include "arcade/skill_check.hpp"
#include "chat.hpp"
#include "arcade.hpp"
#include "cheats.hpp"
#include "debug.hpp"
#include "stats.hpp"
#include "interact.hpp"
#include "inventory.hpp"
#include "text.hpp"
#include "../../util/imgui/window_slide.hpp"
@@ -18,27 +18,24 @@ namespace game::state::play
class Menu
{
public:
SkillCheck skillCheck;
Chat chat;
Arcade arcade;
Interact interact;
Cheats cheats;
Debug debug;
Stats stats;
Inventory inventory;
state::SettingsMenu settingsMenu;
#if DEBUG
bool isCheats{true};
#elif
#else
bool isCheats{};
#endif
bool isOpen{true};
bool isChat{true};
util::imgui::WindowSlide slide{};
void tick();
void update(Resources&, ItemManager&, entity::Character&, entity::Cursor&, Text&, Canvas&);
void color_set_check(Resources&, entity::Character&);
};
}

View File

@@ -1,48 +0,0 @@
#include "stats.hpp"
#include <ranges>
#include "../../util/measurement.hpp"
using namespace game::resource;
using namespace game::util;
namespace game::state::play
{
void Stats::update(Resources& resources, SkillCheck& skillCheck, entity::Character& character)
{
ImGui::PushFont(ImGui::GetFont(), Font::BIG);
ImGui::TextUnformatted(character.data.name.c_str());
ImGui::PopFont();
ImGui::Separator();
auto& skillCheckSchema = character.data.skillCheckSchema;
auto& system = resources.settings.measurementSystem;
auto weight = character.weight_get(system);
auto weightUnit = system == measurement::IMPERIAL ? "lbs" : "kg";
ImGui::Text("Weight: %0.2f %s (Stage: %i)", weight, weightUnit, character.stage_get() + 1);
ImGui::Text("Capacity: %0.0f kcal (Max: %0.0f kcal)", character.capacity, character.max_capacity());
ImGui::Text("Digestion Rate: %0.2f%%/sec", character.digestion_rate_get());
ImGui::Text("Eating Speed: %0.2fx", character.eatSpeed);
ImGui::SeparatorText("Totals");
ImGui::Text("Total Calories Consumed: %0.0f kcal", character.totalCaloriesConsumed);
ImGui::Text("Total Food Items Eaten: %i", character.totalFoodItemsEaten);
ImGui::SeparatorText("Skill Check");
ImGui::Text("Best: %i pts (%ix)", skillCheck.highScore, skillCheck.bestCombo);
ImGui::Text("Total Skill Checks: %i", skillCheck.totalPlays);
for (int i = 0; i < (int)skillCheckSchema.grades.size(); i++)
{
auto& grade = skillCheckSchema.grades[i];
ImGui::Text("%s: %i", grade.namePlural.c_str(), skillCheck.gradeCounts[i]);
}
ImGui::Text("Accuracy: %0.2f%%", skillCheck.accuracy_score_get(character));
}
}

View File

@@ -1,17 +0,0 @@
#pragma once
#include "../../entity/character.hpp"
#include "../../resources.hpp"
#include "arcade/skill_check.hpp"
#include <imgui.h>
namespace game::state::play
{
class Stats
{
public:
void update(Resources&, SkillCheck&, entity::Character&);
};
}

14
src/state/play/style.hpp Normal file
View File

@@ -0,0 +1,14 @@
#pragma once
#include "../../entity/character.hpp"
#include "../../resources.hpp"
#include "../../util/imgui/style.hpp"
namespace game::state::play::style
{
inline void color_set(Resources& resources, const entity::Character& character)
{
game::util::imgui::style::color_set(resources.settings.isUseCharacterColor ? character.data.color
: resources.settings.color);
}
}

View File

@@ -37,10 +37,12 @@ namespace game::state::play
index = 0;
time = 0.0f;
isEnabled = true;
character.isTalking = true;
if (!dialogueEntry->animation.empty())
character.queue_play({.animation = dialogueEntry->animation, .isInterruptible = isInterruptible});
if (dialogueEntry->text.empty()) isEnabled = false;
if (dialogueEntry->text.empty())
isEnabled = false;
else
character.isTalking = true;
}
void Text::tick(entity::Character& character)
@@ -48,6 +50,8 @@ namespace game::state::play
if (!entry || isFinished) return;
index++;
auto blipPeriod = character.data.textBlipPeriodBase;
if (blipPeriod > 0 && index % blipPeriod == 0) character.data.sounds.blip.play();
if (index >= ImTextCountCharsFromUtf8(entry->text.c_str(), entry->text.c_str() + entry->text.size()))
{

View File

@@ -7,6 +7,7 @@
using namespace game::util;
using namespace game::util::imgui;
using namespace game::resource::xml;
namespace game::state::play
{
@@ -18,6 +19,7 @@ namespace game::state::play
auto style = ImGui::GetStyle();
auto& io = ImGui::GetIO();
auto& schema = character.data.menuSchema;
auto& strings = character.data.strings;
slide.update(isOpen, io.DeltaTime);
@@ -56,8 +58,9 @@ namespace game::state::play
ImGui::PopStyleColor();
};
if (WIDGET_FX(ImGui::Button("Home", buttonSize))) world.character_focus(character, canvas, focus);
ImGui::SetItemTooltip("%s", "Reset camera view.\n(Shortcut: Home)");
if (WIDGET_FX(ImGui::Button(strings.get(Strings::ToolsHomeButton).c_str(), buttonSize)))
world.character_focus(character, canvas, focus);
ImGui::SetItemTooltip("%s", strings.get(Strings::ToolsHomeTooltip).c_str());
for (int i = 0; i < (int)character.data.interactTypeNames.size(); i++)
cursor_mode_button(character.data.interactTypeNames[i], i);
@@ -82,7 +85,9 @@ namespace game::state::play
if (t <= 0.0f || t >= 1.0f)
{
ImGui::SetItemTooltip(isOpen ? "Close Tools" : "Open Tools");
ImGui::SetItemTooltip("%s", strings.get(isOpen ? Strings::ToolsCloseTooltip
: Strings::ToolsOpenTooltip)
.c_str());
if (result)
{
isOpen = !isOpen;

View File

@@ -62,6 +62,7 @@ namespace game::state::play
{
static constexpr float MENU_WIDTH_MULTIPLIER = 0.30f;
static constexpr float TOOLS_WIDTH_MULTIPLIER = 0.10f;
static constexpr float INFO_HEIGHT_MULTIPLIER = 4.0f;
static constexpr float PADDING = 100.0f;
auto rect = character.rect();
@@ -72,13 +73,18 @@ namespace game::state::play
rect = {rect.x - PADDING * 0.5f, rect.y - PADDING * 0.5f, rect.z + PADDING, rect.w + PADDING};
auto zoomFactor = std::min((float)canvas.size.x / rect.z, (float)canvas.size.y / rect.w);
auto infoHeightPixels =
ImGui::GetTextLineHeightWithSpacing() * INFO_HEIGHT_MULTIPLIER + ImGui::GetStyle().WindowPadding.y * 2.0f;
auto usableHeightPixels = std::max(1.0f, (float)canvas.size.y - infoHeightPixels);
auto zoomFactor = std::min((float)canvas.size.x / rect.z, usableHeightPixels / rect.w);
canvas.zoom = glm::clamp(ZOOM_MIN, math::to_percent(zoomFactor), ZOOM_MAX);
zoomFactor = math::to_unit(canvas.zoom);
auto rectCenter = glm::vec2(rect.x + rect.z * 0.5f, rect.y + rect.w * 0.5f);
auto viewSizeWorld = glm::vec2(canvas.size) / zoomFactor;
canvas.pan = rectCenter - (vec2(viewSizeWorld.x, viewSizeWorld.y) * 0.5f);
auto infoHeightWorld = infoHeightPixels / zoomFactor;
canvas.pan = rectCenter - vec2(viewSizeWorld.x * 0.5f, (viewSizeWorld.y + infoHeightWorld) * 0.5f);
auto menuWidthWorld = (canvas.size.x * MENU_WIDTH_MULTIPLIER) / zoomFactor;
auto toolsWidthWorld = (canvas.size.x * TOOLS_WIDTH_MULTIPLIER) / zoomFactor;

View File

@@ -47,38 +47,51 @@ namespace game::state::select
ImGui::TextUnformatted(character.name.c_str());
ImGui::PopFont();
if (!character.description.empty())
{
ImGui::Separator();
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(imgui::to_imvec4(color::GRAY)));
ImGui::PushFont(ImGui::GetFont(), Font::BIG);
ImGui::TextWrapped("%s", character.description.c_str());
ImGui::PopFont();
ImGui::PopStyleColor();
}
ImGui::Separator();
ImGui::PushFont(ImGui::GetFont(), Font::BIG);
ImGui::Text("Weight: %0.2f %s", system == IMPERIAL ? weight * KG_TO_LB : weight,
system == IMPERIAL ? "lbs" : "kg");
ImGui::Text("Stages: %i", character.stages);
ImGui::Separator();
ImGui::PopFont();
ImGui::PushFont(ImGui::GetFont(), Font::NORMAL);
if (ImGui::BeginTabBar("##Preview Tabs"))
{
if (ImGui::BeginTabItem("Overview"))
{
if (!character.description.empty())
{
ImGui::Separator();
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(imgui::to_imvec4(color::GRAY)));
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(imgui::to_imvec4(color::GRAY)));
ImGui::PushFont(ImGui::GetFont(), Font::HEADER_2);
ImGui::TextWrapped("%s", character.description.c_str());
ImGui::PopFont();
if (!character.author.empty()) ImGui::TextWrapped("Author: %s", character.author.c_str());
ImGui::PopStyleColor();
}
ImGui::PopStyleColor();
ImGui::Separator();
ImGui::PushFont(ImGui::GetFont(), Font::HEADER_2);
ImGui::Text("Weight: %0.2f %s", system == IMPERIAL ? weight * KG_TO_LB : weight,
system == IMPERIAL ? "lbs" : "kg");
ImGui::Text("Stages: %i", character.stages);
ImGui::PopFont();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Credits"))
{
ImGui::Separator();
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(imgui::to_imvec4(color::GRAY)));
ImGui::PushFont(ImGui::GetFont(), Font::HEADER_2);
if (!character.credits.empty())
ImGui::TextWrapped("%s", character.credits.c_str());
else
ImGui::TextUnformatted("No credits listed.");
ImGui::PopFont();
ImGui::PopStyleColor();
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
ImGui::PopFont();
}
ImGui::EndChild();

View File

@@ -54,7 +54,7 @@ namespace game::state::select
auto renderSize = ImVec2(textureSize.x * scale, textureSize.y * scale);
ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + (availableSize.x * 0.5f) - (renderSize.y * 0.5f),
ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + (availableSize.x * 0.5f) - (renderSize.x * 0.5f),
ImGui::GetCursorPosY() + (availableSize.y * 0.5f) - (renderSize.y * 0.5f)));
ImGui::Image(character.render.id, renderSize);

View File

@@ -10,47 +10,61 @@
using namespace game::util;
using namespace game::util::imgui;
using namespace game::resource::xml;
namespace game::state
{
void SettingsMenu::update(Resources& resources, Mode mode)
void SettingsMenu::update(Resources& resources, Mode mode, const Strings* strings)
{
auto& settings = resources.settings;
auto& measurementSystem = settings.measurementSystem;
auto& volume = settings.volume;
auto& color = settings.color;
auto string_get = [&](Strings::Type type, const char* fallback) -> const char*
{
return strings ? strings->get(type).c_str() : fallback;
};
isJustColorSet = false;
ImGui::SeparatorText("Measurement System");
WIDGET_FX(ImGui::RadioButton("Metric", (int*)&measurementSystem, measurement::METRIC));
ImGui::SetItemTooltip("%s", "Use kilograms (kg).");
ImGui::SeparatorText(string_get(Strings::SettingsMeasurementSystem, "Measurement System"));
WIDGET_FX(ImGui::RadioButton(string_get(Strings::SettingsMetric, "Metric"),
(int*)&measurementSystem, measurement::METRIC));
ImGui::SetItemTooltip("%s", string_get(Strings::SettingsMetricTooltip, "Use kilograms (kg)."));
ImGui::SameLine();
WIDGET_FX(ImGui::RadioButton("Imperial", (int*)&measurementSystem, measurement::IMPERIAL));
ImGui::SetItemTooltip("%s", "Use pounds (lbs).");
WIDGET_FX(ImGui::RadioButton(string_get(Strings::SettingsImperial, "Imperial"),
(int*)&measurementSystem, measurement::IMPERIAL));
ImGui::SetItemTooltip("%s", string_get(Strings::SettingsImperialTooltip, "Use pounds (lbs)."));
ImGui::SeparatorText("Sound");
if (WIDGET_FX(ImGui::SliderInt("Volume", &volume, 0, 100, "%d%%")))
ImGui::SeparatorText(string_get(Strings::SettingsSound, "Sound"));
if (WIDGET_FX(
ImGui::SliderInt(string_get(Strings::SettingsVolume, "Volume"), &volume, 0, 100, "%d%%")))
resources.volume_set(math::to_unit((float)volume));
ImGui::SetItemTooltip("%s", "Adjust master volume.");
ImGui::SetItemTooltip("%s", string_get(Strings::SettingsVolumeTooltip, "Adjust master volume."));
ImGui::SeparatorText("Appearance");
ImGui::SeparatorText(string_get(Strings::SettingsAppearance, "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.");
if (WIDGET_FX(ImGui::Checkbox(string_get(Strings::SettingsUseCharacterColor,
"Use Character Color"),
&settings.isUseCharacterColor)))
isJustColorSet = true;
ImGui::SetItemTooltip("%s", string_get(Strings::SettingsUseCharacterColorTooltip,
"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)))
ImGui::ColorEdit3(string_get(Strings::SettingsColor, "Color"), value_ptr(color),
ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoTooltip)))
{
style::color_set(color);
isJustColorSet = true;
}
ImGui::SetItemTooltip("%s", "Change the UI color.");
ImGui::SetItemTooltip("%s", string_get(Strings::SettingsColorTooltip, "Change the UI color."));
ImGui::EndDisabled();
ImGui::Separator();
if (WIDGET_FX(ImGui::Button("Reset to Default", ImVec2(-FLT_MIN, 0))))
if (WIDGET_FX(ImGui::Button(string_get(Strings::SettingsResetButton, "Reset to Default"),
ImVec2(-FLT_MIN, 0))))
{
settings = resource::xml::Settings();
style::color_set(settings.color);
@@ -60,11 +74,19 @@ namespace game::state
{
ImGui::Separator();
if (WIDGET_FX(ImGui::Button("Save", ImVec2(-FLT_MIN, 0)))) isSave = true;
ImGui::SetItemTooltip("%s", "Save the game.\n(Note: the game autosaves frequently.)");
if (WIDGET_FX(
ImGui::Button(string_get(Strings::SettingsSaveButton, "Save"), ImVec2(-FLT_MIN, 0))))
isSave = true;
ImGui::SetItemTooltip(
"%s", string_get(Strings::SettingsSaveTooltip,
"Save the game.\n(Note: the game autosaves frequently.)"));
if (WIDGET_FX(ImGui::Button("Return to Characters", ImVec2(-FLT_MIN, 0)))) isGoToSelect = true;
ImGui::SetItemTooltip("%s", "Go back to the character selection screen.\nProgress will be saved.");
if (WIDGET_FX(ImGui::Button(
string_get(Strings::SettingsReturnToCharactersButton, "Return to Characters"),
ImVec2(-FLT_MIN, 0))))
isGoToSelect = true;
ImGui::SetItemTooltip("%s", string_get(Strings::SettingsReturnToCharactersTooltip,
"Go back to the character selection screen.\nProgress will be saved."));
}
}
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "../resource/xml/strings.hpp"
#include "../resources.hpp"
namespace game::state
@@ -17,6 +18,6 @@ namespace game::state
bool isSave{};
bool isJustColorSet{};
void update(Resources&, Mode = SELECT);
void update(Resources&, Mode = SELECT, const resource::xml::Strings* = nullptr);
};
}