diff --git a/soh/soh/Enhancements/randomizer/logic_expression.cpp b/soh/soh/Enhancements/randomizer/logic_expression.cpp index 3830bcb41..2a61ddabf 100644 --- a/soh/soh/Enhancements/randomizer/logic_expression.cpp +++ b/soh/soh/Enhancements/randomizer/logic_expression.cpp @@ -222,13 +222,13 @@ class Parser { expr->type = LogicExpression::Type::Value; expr->value = token.Text; if (token.Type == LETokenType::Boolean) - expr->valueType = LogicExpression::Impl::ValueType::Boolean; + expr->valueType = LogicExpression::ValueType::Boolean; else if (token.Type == LETokenType::Number) - expr->valueType = LogicExpression::Impl::ValueType::Number; + expr->valueType = LogicExpression::ValueType::Number; else if (token.Type == LETokenType::EnumConstant) - expr->valueType = LogicExpression::Impl::ValueType::Enum; + expr->valueType = LogicExpression::ValueType::Enum; else - expr->valueType = LogicExpression::Impl::ValueType::Identifier; + expr->valueType = LogicExpression::ValueType::Identifier; } } @@ -382,6 +382,10 @@ LogicExpression::Type LogicExpression::GetType() const { return impl->type; } +LogicExpression::ValueType LogicExpression::GetValueType() const { + return impl->valueType; +} + std::string LogicExpression::GetOperation() const { return impl->operation; } diff --git a/soh/soh/Enhancements/randomizer/logic_expression.h b/soh/soh/Enhancements/randomizer/logic_expression.h index 61672c0b4..6049de1f1 100644 --- a/soh/soh/Enhancements/randomizer/logic_expression.h +++ b/soh/soh/Enhancements/randomizer/logic_expression.h @@ -18,11 +18,13 @@ class LogicExpression { const std::string&, const ValueVariant&)>; enum class Type { And, Or, Not, Comparison, FunctionCall, Value, Add, Subtract, Multiply, Divide, Ternary }; + enum class ValueType { Identifier, Boolean, Number, Enum }; static std::shared_ptr Parse(const std::string& exprStr); std::string ToString() const; const std::vector>& GetChildren() const; Type GetType() const; + ValueType GetValueType() const; std::string GetOperation() const; std::string GetFunctionName() const; @@ -60,9 +62,6 @@ class LogicExpression { private: struct Impl { - - enum class ValueType { Identifier, Boolean, Number, Enum }; - Type type; ValueType valueType; std::string value; diff --git a/soh/soh/Enhancements/randomizer/randomizer_logic_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_logic_tracker.cpp index 1d7b979f3..caca85ede 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_logic_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_logic_tracker.cpp @@ -51,8 +51,16 @@ struct LogicTrackerNode { RandomizerRegion RandomizerRegion = RR_NONE; }; +struct RandomizerEventInfo { + std::string ConditionStr; + RandomizerRegion RandomizerRegion = RR_NONE; +}; + +std::unordered_map> randomizerEventMap; + bool expandingNode = false; int expandNodeId = -1; +int clearNodesAfterNodeID = -1; std::vector nodes; static ExpressionTable::ExpressionRow CreateExpressionRows(const std::shared_ptr& expression) { @@ -274,6 +282,52 @@ static void CalculateShowRandomizerRegion() { showFromRandomizerRegion = RR_NONE; } +std::string showEvent = ""; + +void LogicTrackerWindow::ShowRandomizerEvent(const std::string& event) { + showEvent = event; +} + +static void CalculateShowRandomizerEvent() { + if (showEvent.empty()) { + return; + } + + const auto& eventes = randomizerEventMap.find(showEvent); + if (eventes == randomizerEventMap.end()) { + return; + } + + LogicTrackerNode node; + node.NodeName = "Event: " + showEvent; + node.NodeId = nodes.size(); + + for (const auto& eventInfo : eventes->second) { + const auto& region = areaTable[eventInfo.RandomizerRegion]; + + LogicTrackerNode::Connection connection; + connection.ParentName = "Region: " + region.regionName; + connection.ParentRandomizerRegion = eventInfo.RandomizerRegion; + connection.ChildDayAccess = region.childDay; + connection.ChildNightAccess = region.childNight; + connection.AdultDayAccess = region.adultDay; + connection.AdultNightAccess = region.adultNight; + + PopulateConnectionExpression(connection, eventInfo.ConditionStr); + + node.Connections.emplace_back(std::move(connection)); + } + + nodes.emplace_back(std::move(node)); + + auto window = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Logic Tracker"); + window->Show(); + ImGui::SetWindowFocus(window->GetName().c_str()); + expandNodeId = node.NodeId; + + showEvent.clear(); +} + static std::string ToString(const std::optional& value) { if (!value.has_value()) { return ""; @@ -362,15 +416,18 @@ static void DrawCondition(const LogicExpression& expression) { } } -static void DrawExpressionRow(const ExpressionTable& table, ExpressionTable::ExpressionRow& row, int level) { +static void DrawExpressionRow(const LogicTrackerNode& node, const ExpressionTable& table, + ExpressionTable::ExpressionRow& row, int level) { + const auto& expression = *row.Expression; + ImGui::TableNextRow(); + ImGui::PushID(&row); ImGui::PushFont(OTRGlobals::Instance->fontMono); if (level > 0) { ImGui::Indent(20.0f); } ImGui::TableNextColumn(); - ImGui::PushID(&row); if (!row.Children.empty()) { if (ImGui::Button(std::to_string(level).c_str())) { row.Expanded = !row.Expanded; @@ -379,11 +436,26 @@ static void DrawExpressionRow(const ExpressionTable& table, ExpressionTable::Exp ImGui::BeginDisabled(); ImGui::Button(std::to_string(level).c_str()); ImGui::EndDisabled(); + + if (expression.GetType() == LogicExpression::Type::Value && + expression.GetValueType() == LogicExpression::ValueType::Identifier) { + std::string identifier = expression.ToString(); + auto it = randomizerEventMap.find(identifier); + if (it != randomizerEventMap.end()) { + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_COGS)) { + LogicTrackerWindow::ShowRandomizerEvent(identifier); + clearNodesAfterNodeID = node.NodeId; + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Show Event Logic"); + } + } + } } - ImGui::PopID(); ImGui::TableNextColumn(); - DrawCondition(*row.Expression); + DrawCondition(expression); if (!row.ErrorMessage.empty()) { ImGui::TextWrapped("%s", row.ErrorMessage.c_str()); } @@ -408,7 +480,7 @@ static void DrawExpressionRow(const ExpressionTable& table, ExpressionTable::Exp if (row.Expanded) { for (auto& child : row.Children) { - DrawExpressionRow(table, child, level + 1); + DrawExpressionRow(node, table, child, level + 1); } } @@ -416,9 +488,10 @@ static void DrawExpressionRow(const ExpressionTable& table, ExpressionTable::Exp ImGui::Unindent(20.0f); } ImGui::PopFont(); + ImGui::PopID(); } -static void DrawExpressionTable(ExpressionTable& table) { +static void DrawExpressionTable(const LogicTrackerNode& node, ExpressionTable& table) { int columnCount = 3; if (!table.CombineAll) { if (!table.CombineChild) { @@ -453,13 +526,13 @@ static void DrawExpressionTable(ExpressionTable& table) { ImGui::TableHeadersRow(); } - DrawExpressionRow(table, table.Root, 0); + DrawExpressionRow(node, table, table.Root, 0); ImGui::EndTable(); } -static void DrawNodeConnection(LogicTrackerNode& node, LogicTrackerNode::Connection& connection) { - DrawExpressionTable(connection.ExpressionTable); +static void DrawNodeConnection(const LogicTrackerNode& node, LogicTrackerNode::Connection& connection) { + DrawExpressionTable(node, connection.ExpressionTable); } static std::string GetAccessString(const LogicTrackerNode::Connection& connection) { @@ -558,8 +631,6 @@ static std::string GetAvailableString(const LogicTrackerNode::Connection& connec return available; } -int clearNodesAfterNodeID = -1; - static void DrawNode(LogicTrackerNode& node) { ImGui::PushID(node.NodeId); @@ -620,9 +691,30 @@ static void DrawNode(LogicTrackerNode& node) { ImGui::PopID(); } +static void PopulateRandomizerEventMap() { + if (!randomizerEventMap.empty()) { + return; + } + + for (int i = RR_NONE; i < RR_MAX; i++) { + for (const auto& event : areaTable[i].events) { + const auto& eventStr = event.GetEventStr(); + auto it = randomizerEventMap.find(eventStr); + auto eventInfo = RandomizerEventInfo{ event.GetConditionStr(), RandomizerRegion(i) }; + if (it != randomizerEventMap.end()) { + it->second.emplace_back(std::move(eventInfo)); + } else { + randomizerEventMap.emplace(eventStr, std::vector{ std::move(eventInfo) }); + } + } + } +} + void LogicTrackerWindow::DrawElement() { + PopulateRandomizerEventMap(); CalculateShowRandomizerCheck(); CalculateShowRandomizerRegion(); + CalculateShowRandomizerEvent(); if (expandNodeId != -1) { expandingNode = true; diff --git a/soh/soh/Enhancements/randomizer/randomizer_logic_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_logic_tracker.h index 65a0ffb42..a89b2fab2 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_logic_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_logic_tracker.h @@ -10,6 +10,7 @@ class LogicTrackerWindow : public Ship::GuiWindow { static void ShowRandomizerCheck(RandomizerCheck randomizerCheck); static void ShowRandomizerRegion(RandomizerRegion toRandomizerRegion, RandomizerRegion fromRandomizerRegion); + static void ShowRandomizerEvent(const std::string& event); protected: void InitElement() override;