Files
Shiip-of-Hakinian-Espanol/soh/soh/Enhancements/RogueLike/GUI/GUI.cpp
Garrett Cox 2b9acd888b More last minute fixes (#37)
* More last minute fixes

* tweaks to RogueLike

* Add random GBK requirement
2025-12-07 09:55:52 -07:00

544 lines
23 KiB
C++

#include "soh/Enhancements/RogueLike/RogueLike.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"
#include "soh/SohGui/SohMenu.h"
#include "soh/Enhancements/randomizer/3drando/random.hpp"
extern "C" {
#include "variables.h"
extern PlayState* gPlayState;
}
namespace SohGui {
extern std::shared_ptr<SohMenu> mSohMenu;
}
#define QUEST_TO_TEXTURE(id) \
{ id, #id }
std::map<uint32_t, const char*> questToTexture = {
QUEST_TO_TEXTURE(QUEST_MEDALLION_FOREST), QUEST_TO_TEXTURE(QUEST_MEDALLION_FIRE),
QUEST_TO_TEXTURE(QUEST_MEDALLION_WATER), QUEST_TO_TEXTURE(QUEST_MEDALLION_SPIRIT),
QUEST_TO_TEXTURE(QUEST_MEDALLION_SHADOW), QUEST_TO_TEXTURE(QUEST_MEDALLION_LIGHT),
QUEST_TO_TEXTURE(QUEST_KOKIRI_EMERALD), QUEST_TO_TEXTURE(QUEST_GORON_RUBY),
QUEST_TO_TEXTURE(QUEST_ZORA_SAPPHIRE), QUEST_TO_TEXTURE(QUEST_STONE_OF_AGONY),
QUEST_TO_TEXTURE(QUEST_GERUDO_CARD), QUEST_TO_TEXTURE(QUEST_SKULL_TOKEN),
};
void RogueLike::GUI::BeginFullscreenDimmed(const char* windowName) {
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowSize(viewport->Size);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::Begin(windowName, nullptr,
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar);
ImGui::PopStyleVar();
ImGui::PopStyleVar();
}
static std::vector<RogueLike::Choices::ChoiceCard*> choices = {};
static float rollTimer = 0.0f;
static int rollsRemaining = 0;
RogueLike::Choices::ChoiceCard*
RogueLike::GUI::DrawChooseScreen(std::string heading, std::vector<RogueLike::Choices::ChoiceCard>& allChoices,
int rolls) {
RogueLike::Choices::ChoiceCard* selectedChoice = nullptr;
ImVec2 outerCardSize = ImVec2(300, 400);
ImVec2 innerCardSize = ImVec2(outerCardSize.x - 40, outerCardSize.y - 40);
ImVec2 iconSize = ImVec2(125, 125);
// Heading
ImGui::SetWindowFontScale(2.0f);
ImGui::SetCursorPosY(ImGui::GetWindowHeight() / 2 - (outerCardSize.y / 2) - 100);
ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize(heading.c_str()).x) / 2);
ImGui::Text("%s", heading.c_str());
ImGui::SetWindowFontScale(1.0f);
// Cards
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
if (choices.size() == 0) {
choices = RogueLike::Choices::Choose3Max(allChoices);
rollTimer = 0.0f;
if (choices.size() > 2) {
rollsRemaining = rolls;
choices.resize(2);
} else {
rollsRemaining = 0;
}
}
if (rollsRemaining > 0) {
rollTimer += ImGui::GetIO().DeltaTime;
if (rollTimer >= 0.05f) {
rollTimer = 0.0f;
rollsRemaining--;
choices = RogueLike::Choices::Choose3Max(allChoices);
if (choices.size() > 2) {
choices.resize(2);
}
}
}
float cardStartX = (ImGui::GetWindowWidth() - (outerCardSize.x * choices.size())) / 2;
float cardStartY = ImGui::GetWindowHeight() / 2 - (outerCardSize.y / 2);
ImGui::SetCursorPosX(cardStartX);
ImGui::SetCursorPosY(cardStartY);
static int cachedHoverIndex = -1;
int hoverIndex = -1;
for (size_t i = 0; i < choices.size(); i++) {
if (i > 0) {
ImGui::SameLine();
}
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20, 20));
ImGui::BeginChild(("card" + std::to_string(i)).c_str(), outerCardSize, ImGuiChildFlags_AlwaysUseWindowPadding);
ImGui::PopStyleVar();
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 10.0f);
ImGui::PushStyleColor(ImGuiCol_ChildBg, (cachedHoverIndex == static_cast<int>(i))
? ImVec4(0.2f, 0.2f, 0.2f, 1.0f)
: ImVec4(0.1f, 0.1f, 0.1f, 1.0f));
ImGui::BeginChild(("card_content" + std::to_string(i)).c_str(), ImVec2(-1, -1), 0);
ImGui::PopStyleColor();
ImGui::PopStyleVar();
if (choices[i]->textureName.substr(0, 10) == "QUEST_SONG") {
// Songs are thinner
iconSize = ImVec2(100, 150);
}
ImGui::SetCursorPosX(innerCardSize.x / 2 - iconSize.x / 2);
ImGui::SetCursorPosY(innerCardSize.y / 2 - iconSize.y / 2 - 20);
ImTextureID textureId =
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(choices[i]->textureName);
ImGui::Image(textureId, iconSize);
ImGui::SetCursorPosX(innerCardSize.x / 2 - ImGui::CalcTextSize(choices[i]->name.c_str()).x / 2);
ImGui::SetCursorPosY(innerCardSize.y - 75);
if (rollsRemaining == 0) {
ImGui::Text("%s", choices[i]->name.c_str());
}
ImGui::EndChild();
if (ImGui::IsItemHovered() && rollsRemaining == 0) {
hoverIndex = static_cast<int>(i);
}
if (ImGui::IsItemClicked() && rollsRemaining == 0) {
selectedChoice = choices[i];
}
ImGui::EndChild();
}
// Draw button indicators below each card
for (size_t i = 0; i < choices.size(); i++) {
// Draw button indicator
const char* buttonLabel = (i == 0) ? "B" : "A";
float circleRadius = 30.0f;
ImVec2 windowPos = ImGui::GetWindowPos();
ImVec2 circleCenter = ImVec2(windowPos.x + cardStartX + (outerCardSize.x * i) + (outerCardSize.x / 2),
windowPos.y + cardStartY + outerCardSize.y + 70);
ImDrawList* drawList = ImGui::GetWindowDrawList();
drawList->AddCircleFilled(circleCenter, circleRadius,
rollsRemaining == 0
? ((i == 0) ? IM_COL32(0, 150, 0, 255) : IM_COL32(20, 20, 190, 255))
: IM_COL32(100, 100, 100, 255));
drawList->AddCircle(circleCenter, circleRadius, IM_COL32(0, 0, 0, 100), 0, 4.0f);
ImVec2 textSize = ImGui::CalcTextSize(buttonLabel);
ImVec2 textPos = ImVec2(circleCenter.x - textSize.x / 2, circleCenter.y - textSize.y / 2);
drawList->AddText(textPos, IM_COL32(255, 255, 255, 255), buttonLabel);
}
if (hoverIndex != -1) {
cachedHoverIndex = hoverIndex;
} else {
cachedHoverIndex = -1;
}
ImGui::PopStyleVar();
if (rollsRemaining == 0) {
Input* input = &gPlayState->state.input[0];
if (CHECK_BTN_ANY(input->press.button, BTN_A) && choices.size() > 1) {
selectedChoice = choices[1];
input->press.button &= ~BTN_A;
}
if (CHECK_BTN_ANY(input->press.button, BTN_B)) {
selectedChoice = choices[0];
input->press.button &= ~BTN_B;
}
}
if (selectedChoice != nullptr) {
choices.clear();
}
return selectedChoice;
}
std::map<RoguelikeStats, std::pair<std::string, std::string>> rogueLikeStatMap = {
{ RL_HEALTH, { "Health", "ITEM_HEART_CONTAINER" } },
{ RL_ATTACK, { "Attack", "ITEM_SWORD_MASTER" } },
{ RL_DEFENSE, { "Defense", "ITEM_SHIELD_HYLIAN" } },
{ RL_SPEED, { "Speed", "ITEM_MASK_BUNNY" } },
};
std::vector<RogueLikeQuestObject> activeQuests;
void TableCellVerticalCenteredText(ImVec4 color, const char* text) {
float textHeight = ImGui::GetTextLineHeight();
float offsetX = (32.0f - textHeight + 10.0f) * 0.5f;
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + offsetX);
ImGui::TextColored(color, text);
}
void TableCellHorizontalCenteredText(ImVec4 color, const char* text) {
float cellWidth = ImGui::GetContentRegionAvail().x;
float textWidth = ImGui::CalcTextSize(text).x;
float offsetX = (cellWidth - textWidth) * 0.5f;
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
ImGui::TextColored(color, text);
}
bool TableCellCenteredImageButton(const char* id, ImTextureID texture) {
float cellWidth = ImGui::GetContentRegionAvail().x;
float offsetX = (cellWidth - 46.0f) * 0.5f;
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
return ImGui::ImageButton(id, texture, ImVec2(46.0f, 46.0f));
}
void RogueLike::GUI::HUDWindow::Draw() {
if (!IsVisible()) {
return;
}
// Full screen overlay
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowSize(viewport->Size);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::Begin("RogueLike HUD", nullptr,
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground);
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f);
if (ImGui::BeginChild("StatsWindow")) {
if (ImGui::BeginTable("StatsList", 3, ImGuiTableFlags_SizingFixedFit)) {
ImTextureID textureId =
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("ITEM_RUPEE_GREEN");
ImGui::TableNextColumn();
ImGui::Image(textureId, ImVec2(46.0f, 46.0f));
ImGui::TableNextColumn();
TableCellVerticalCenteredText(ImVec4(1, 1, 1, 1), "Level");
ImGui::TableNextColumn();
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 9.0f);
ImGui::ProgressBar(RogueLike::XP::GetProgressToNextLevel(), ImVec2(200, 0),
(std::to_string(RogueLike::XP::GetCurrentLevel()) + " (" +
std::to_string(static_cast<int>(RogueLike::XP::GetProgressToNextLevel() * 100)) + "%)")
.c_str());
ImTextureID textureId2 =
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("ITEM_MASK_SKULL");
ImGui::TableNextColumn();
ImGui::Image(textureId2, ImVec2(46.0f, 46.0f));
ImGui::TableNextColumn();
TableCellVerticalCenteredText(ImVec4(1, 1, 1, 1), "Difficulty");
ImGui::TableNextColumn();
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 9.0f);
ImGui::ProgressBar(
RogueLike::Difficulty::GetProgressToNextLevel(), ImVec2(200, 0),
(std::to_string(RogueLike::Difficulty::GetCurrentLevel()) + " (" +
std::to_string(static_cast<int>(RogueLike::Difficulty::GetProgressToNextLevel() * 100)) + "%)")
.c_str());
for (auto& stat : rogueLikeStatMap) {
ImTextureID textureId =
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(stat.second.second);
std::string statValueStr = gSaveContext.ship.quest.data.rogueLike.stats[stat.first] >= 0 ? "+" : "-";
statValueStr += std::to_string(gSaveContext.ship.quest.data.rogueLike.stats[stat.first]).c_str();
ImGui::TableNextColumn();
ImGui::Image(textureId, ImVec2(46.0f, 46.0f));
ImGui::TableNextColumn();
TableCellVerticalCenteredText(ImVec4(1, 1, 1, 1), stat.second.first.c_str());
ImGui::TableNextColumn();
TableCellVerticalCenteredText(ImVec4(0, 1, 0, 1), statValueStr.c_str());
}
ImGui::TableNextColumn();
ImGui::TableNextColumn();
TableCellVerticalCenteredText(ImVec4(1, 1, 1, 1), "Required Dungeon Rewards:");
ImGui::TableNextColumn();
ImGui::TableNextColumn();
ImGui::TableNextColumn();
for (auto& reward : RogueLike::requiredRewards) {
if (reward != RogueLike::requiredRewards[0]) {
ImGui::SameLine();
}
auto tint = CHECK_QUEST_ITEM(reward) ? ImVec4(1, 1, 1, 1) : ImVec4(1, 1, 1, 0.5f);
ImTextureID textureId =
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(questToTexture[reward]);
ImGui::Image(textureId, ImVec2(25.0f, 25.0f), ImVec2(0.0f, 0.0f), ImVec2(1, 1), tint,
ImVec4(0, 0, 0, 0));
}
ImGui::EndTable();
if (ImGui::BeginChild("QuestWindow", ImVec2(300.0f, 0))) {
if (activeQuests.size() != 0) {
ImVec4 completionColor = ImVec4(1, 1, 1, 1);
for (auto& quests : activeQuests) {
if (quests.questProgress == quests.questGoal || quests.questStatus == RL_QUEST_COMPLETE) {
completionColor = ImVec4(0, 1, 0, 1);
}
ImGui::SeparatorText(quests.questName);
if (quests.questStatus != RL_QUEST_COMPLETE) {
ImGui::Text(quests.questDescription);
std::string questProgressStr = std::to_string(quests.questProgress).c_str();
questProgressStr += " / ";
questProgressStr += std::to_string(quests.questGoal).c_str();
TableCellHorizontalCenteredText(completionColor, questProgressStr.c_str());
} else {
TableCellHorizontalCenteredText(completionColor, "Quest Complete");
}
ImGui::Separator();
}
}
ImGui::EndChild();
}
}
ImGui::EndChild();
}
ImGui::PopStyleColor(1);
ImGui::PopStyleVar(1);
ImGui::End();
}
std::shared_ptr<RogueLike::GUI::StartingSelectionWindow> mStartingSelectionWindow;
std::shared_ptr<RogueLike::GUI::HUDWindow> mHUDWindow;
std::shared_ptr<RogueLike::GUI::LevelUpWindow> mLevelUpWindow;
// Entry point for the module, run once on game boot
static void InitRogueLikeGUI() {
CVarClear(CVAR_WINDOW("RogueLikeStartingSelection"));
CVarClear(CVAR_WINDOW("RogueLikeHUD"));
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
mStartingSelectionWindow = std::make_shared<RogueLike::GUI::StartingSelectionWindow>(
CVAR_WINDOW("RogueLikeStartingSelection"), "RogueLike Starting Selection");
gui->AddGuiWindow(mStartingSelectionWindow);
mHUDWindow = std::make_shared<RogueLike::GUI::HUDWindow>(CVAR_WINDOW("RogueLikeHUD"), "RogueLike HUD");
gui->AddGuiWindow(mHUDWindow);
mLevelUpWindow =
std::make_shared<RogueLike::GUI::LevelUpWindow>(CVAR_WINDOW("RogueLikeLevelUp"), "RogueLike Level Up");
gui->AddGuiWindow(mLevelUpWindow);
SohGui::mSohMenu->AddSidebarEntry("Holiday", "RogueLike", 2);
WidgetPath path = { "Holiday", "RogueLike", SECTION_COLUMN_2 };
SohGui::mSohMenu->AddWidget(path, "RogueLikeRight", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) {
if (UIWidgets::Button("Reset All", UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline))) {
CVarSetFloat("gRogueLike.BaseDifficulty", 5000.0f);
CVarSetFloat("gRogueLike.DifficultyGrowthRate", 1.3f);
CVarSetFloat("gRogueLike.BaseXP", 100.0f);
CVarSetFloat("gRogueLike.XPGrowthRate", 1.3f);
CVarSetInteger("gRogueLike.EnemyPlateMax", 3);
CVarSetInteger("gRogueLike.EnemyPlateChance", 25);
CVarSetInteger("gRogueLike.XPDrop.Enemies", 50);
CVarSetInteger("gRogueLike.XPDrop.Bosses", 200);
CVarSetInteger("gRogueLike.XPDrop.BusinessScrubs", 100);
CVarSetInteger("gRogueLike.XPDrop.Chests", 50);
CVarSetInteger("gRogueLike.XPDrop.Grass", 20);
CVarSetInteger("gRogueLike.XPDrop.Pots", 20);
CVarSetInteger("gRogueLike.XPDrop.Rocks", 20);
CVarSetInteger("gRogueLike.XPDrop.Trees", 20);
}
ImGui::SeparatorText("Scaling Options:");
UIWidgets::CVarSliderFloat(
"Base Difficulty", "gRogueLike.BaseDifficulty",
UIWidgets::FloatSliderOptions().Min(0.0f).Max(10000.0f).DefaultValue(5000.0f).Size(ImVec2(300.0f, 0.0f)));
UIWidgets::CVarSliderFloat(
"Difficulty Growth Rate", "gRogueLike.DifficultyGrowthRate",
UIWidgets::FloatSliderOptions().Min(0.0f).Max(5.0f).DefaultValue(1.3f).Size(ImVec2(300.0f, 0.0f)));
UIWidgets::CVarSliderFloat(
"Base XP Req", "gRogueLike.BaseXP",
UIWidgets::FloatSliderOptions().Min(0.0f).Max(1000.0f).DefaultValue(100.0f).Size(ImVec2(300.0f, 0.0f)));
UIWidgets::CVarSliderFloat(
"XP Growth Rate", "gRogueLike.XPGrowthRate",
UIWidgets::FloatSliderOptions().Min(0.0f).Max(5.0f).DefaultValue(1.3f).Size(ImVec2(300.0f, 0.0f)));
UIWidgets::CVarSliderInt(
"Maximum Enemies Plated", "gRogueLike.EnemyPlateMax",
UIWidgets::IntSliderOptions().Min(0).Max(10).DefaultValue(3).Size(ImVec2(300.0f, 0.0f)));
UIWidgets::CVarSliderInt(
"Chance of Enemy Plating", "gRogueLike.EnemyPlateChance",
UIWidgets::IntSliderOptions().Min(0).Max(100).DefaultValue(25).Size(ImVec2(300.0f, 0.0f)));
ImGui::SeparatorText("XP Drop Rates:");
UIWidgets::CVarSliderInt(
"Enemies", "gRogueLike.XPDrop.Enemies",
UIWidgets::IntSliderOptions().Min(1).Max(1000).DefaultValue(50).Size(ImVec2(300.0f, 0.0f)));
UIWidgets::CVarSliderInt(
"Bosses", "gRogueLike.XPDrop.Bosses",
UIWidgets::IntSliderOptions().Min(1).Max(5000).DefaultValue(200).Size(ImVec2(300.0f, 0.0f)));
UIWidgets::CVarSliderInt(
"Business Scrubs", "gRogueLike.XPDrop.BusinessScrubs",
UIWidgets::IntSliderOptions().Min(1).Max(5000).DefaultValue(100).Size(ImVec2(300.0f, 0.0f)));
UIWidgets::CVarSliderInt(
"Chests", "gRogueLike.XPDrop.Chests",
UIWidgets::IntSliderOptions().Min(1).Max(1000).DefaultValue(50).Size(ImVec2(300.0f, 0.0f)));
UIWidgets::CVarSliderInt(
"Grass", "gRogueLike.XPDrop.Grass",
UIWidgets::IntSliderOptions().Min(1).Max(5000).DefaultValue(20).Size(ImVec2(300.0f, 0.0f)));
UIWidgets::CVarSliderInt(
"Pots", "gRogueLike.XPDrop.Pots",
UIWidgets::IntSliderOptions().Min(1).Max(1000).DefaultValue(20).Size(ImVec2(300.0f, 0.0f)));
UIWidgets::CVarSliderInt(
"Rocks", "gRogueLike.XPDrop.Rocks",
UIWidgets::IntSliderOptions().Min(1).Max(5000).DefaultValue(20).Size(ImVec2(300.0f, 0.0f)));
UIWidgets::CVarSliderInt(
"Trees", "gRogueLike.XPDrop.Trees",
UIWidgets::IntSliderOptions().Min(1).Max(5000).DefaultValue(20).Size(ImVec2(300.0f, 0.0f)));
});
path = { "Holiday", "RogueLike", SECTION_COLUMN_1 };
SohGui::mSohMenu->AddWidget(path, "RogueLikeLeft", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) {
ImGui::TextWrapped(
"RogueLike mode is an unpolished proof of concept that enables you to play through the game doing "
"various things to gain XP and gaining items and progression through random rolls instead of finding them "
"at specific points in the game. There are various settings to tweak the balance on the right hand panel, "
"the current balance has not really been heavily tested so feel free to experiment and share your "
"findings. Also if there is interest some one is welcome to pick this up and polish it into a more "
"complete mode, all of it is open source.\n\n"
"\n"
"To begin, start a new file and select the RogueLike quest mode. Your goal is to beat a random selection "
"of dungeons, which will grant you Ganon's boss key and allow you to finish the game.");
ImGui::SeparatorText("Cheats:");
if (!IS_ROGUELIKE) {
ImGui::TextColored(ImVec4(1, 0, 0, 1), "Must be in a RogueLike save");
return;
}
if (UIWidgets::Button("Add XP Level", UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline))) {
RogueLike::XP::GrantXP(RogueLike::XP::ConvertLevelToXP(RogueLike::XP::GetCurrentLevel() + 1) -
gSaveContext.ship.quest.data.rogueLike.xp + 1);
}
ImGui::SameLine();
if (UIWidgets::Button("Remove XP Level", UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline))) {
gSaveContext.ship.quest.data.rogueLike.xp =
RogueLike::XP::ConvertLevelToXP(RogueLike::XP::GetCurrentLevel() - 1);
}
if (UIWidgets::Button("Add Difficulty Level", UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline))) {
RogueLike::Difficulty::IncrementDifficulty(
RogueLike::Difficulty::ConvertLevelToDifficulty(RogueLike::Difficulty::GetCurrentLevel() + 1) -
gSaveContext.ship.quest.data.rogueLike.difficulty + 1);
}
ImGui::SameLine();
if (UIWidgets::Button("Remove Difficulty Level", UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline))) {
gSaveContext.ship.quest.data.rogueLike.difficulty =
RogueLike::Difficulty::ConvertLevelToDifficulty(RogueLike::Difficulty::GetCurrentLevel() - 1);
}
std::string statPlusValue = "";
std::string statMinusValue = "";
if (ImGui::BeginTable("Stat Testing", 2)) {
for (auto& stat : rogueLikeStatMap) {
ImTextureID textureId =
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(stat.second.second);
statPlusValue = "+ ";
statMinusValue = "- ";
std::string statValueStr = stat.second.first;
statPlusValue += statValueStr;
statMinusValue += statValueStr;
ImGui::TableNextColumn();
if (ImGui::ImageButton(statPlusValue.c_str(), textureId, ImVec2(46.0f, 46.0f))) {
gSaveContext.ship.quest.data.rogueLike.stats[stat.first]++;
RogueLike::XP::UpdatePlayerStats();
}
ImGui::TextColored(ImVec4(0, 1, 0, 1), statPlusValue.c_str());
ImGui::TableNextColumn();
if (ImGui::ImageButton(statMinusValue.c_str(), textureId, ImVec2(46.0f, 46.0f))) {
gSaveContext.ship.quest.data.rogueLike.stats[stat.first]--;
RogueLike::XP::UpdatePlayerStats();
}
ImGui::TextColored(ImVec4(1, 0, 0, 1), statMinusValue.c_str());
}
ImGui::EndTable();
}
});
COND_HOOK(OnExitGame, true, [](int32_t fileNum) {
mStartingSelectionWindow->Hide();
mHUDWindow->Hide();
mLevelUpWindow->Hide();
});
}
static void OnLoadGame() {
mStartingSelectionWindow->Hide();
mHUDWindow->Hide();
mLevelUpWindow->Hide();
if (IS_ROGUELIKE) {
if (gSaveContext.ship.quest.data.rogueLike.lastActivity == 0) {
RogueLike::Difficulty::IndicateActivity();
mStartingSelectionWindow->Show();
}
}
COND_HOOK(OnPlayerUpdate, IS_ROGUELIKE, [] {
if (mStartingSelectionWindow->IsVisible() || mLevelUpWindow->IsVisible()) {
mHUDWindow->Hide();
gPlayState->frameAdvCtx.enabled = true;
} else {
mHUDWindow->Show();
gPlayState->frameAdvCtx.enabled = false;
}
});
}
static RegisterMenuInitFunc menuInitFunc(InitRogueLikeGUI);
static RegisterShipInitFunc initFunc2(OnLoadGame, { "IS_ROGUELIKE" });