diff --git a/sdk/include/mods/svc/flow.hpp b/sdk/include/mods/svc/flow.hpp index 9687a6eebb..c7671f69a6 100644 --- a/sdk/include/mods/svc/flow.hpp +++ b/sdk/include/mods/svc/flow.hpp @@ -100,6 +100,7 @@ public: NodeRef next(uint16_t target) const; /* Set a branch node's result targets */ NodeRef results(std::initializer_list targets) const; + NodeRef results(std::span targets) const; uint16_t id() const { return mId; } operator uint16_t() const { return mId; } @@ -153,6 +154,35 @@ public: } return *this; } + GraphBuilder& patch_branch(uint16_t nodeIndex, FlowQueryId query, uint16_t parameter, + std::span targets) { + if (mResult != MOD_OK || targets.empty() || targets.size() > 0xff) { + if (mResult == MOD_OK) { + mResult = MOD_INVALID_ARGUMENT; + } + return *this; + } + uint16_t first = 0; + mResult = svc_flow->add_edges( + mod_ctx, mHandle, targets.data(), static_cast(targets.size()), &first); + if (mResult == MOD_OK) { + patch_node(nodeIndex, + branch(static_cast(targets.size()), query, parameter, first)); + } + return *this; + } + GraphBuilder& patch_event(uint16_t nodeIndex, FlowEventId eventId, + std::array params, uint16_t target) { + if (mResult != MOD_OK) { + return *this; + } + uint16_t edge = 0; + mResult = svc_flow->add_edges(mod_ctx, mHandle, &target, 1, &edge); + if (mResult == MOD_OK) { + patch_node(nodeIndex, event(eventId, edge, params)); + } + return *this; + } Graph commit() { for (const auto& node : mNodes) { @@ -232,7 +262,7 @@ private: } } - void set_results(uint16_t id, std::initializer_list targets) { + void set_results(uint16_t id, std::span targets) { if (mResult != MOD_OK) { return; } @@ -246,7 +276,7 @@ private: node->wired = true; uint16_t first = 0; mResult = svc_flow->add_edges( - mod_ctx, mHandle, targets.begin(), static_cast(targets.size()), &first); + mod_ctx, mHandle, targets.data(), static_cast(targets.size()), &first); if (mResult == MOD_OK) { node->data.bytes[1] = static_cast(targets.size()); write_bits(node->data.bytes + 6, first); @@ -266,6 +296,10 @@ inline NodeRef NodeRef::next(uint16_t target) const { } inline NodeRef NodeRef::results(std::initializer_list targets) const { + return results(std::span{targets.begin(), targets.size()}); +} + +inline NodeRef NodeRef::results(std::span targets) const { if (mBuilder != nullptr) { mBuilder->set_results(mId, targets); } @@ -368,6 +402,10 @@ public: [[nodiscard]] constexpr MessageStyle face_anim(uint8_t value) const { return set_u8(17, value); } + /* INF1 bytes 18-19, normally 0x0400. */ + [[nodiscard]] constexpr MessageStyle trailing_data(uint16_t value) const { + return set_u16(18, value); + } [[nodiscard]] constexpr const MessageEntryData& data() const { return mData; } private: @@ -432,6 +470,9 @@ public: MessageBuilder& camera_attr(uint8_t value) { return style(&MessageStyle::camera_attr, value); } MessageBuilder& talk_anim(uint8_t value) { return style(&MessageStyle::talk_anim, value); } MessageBuilder& face_anim(uint8_t value) { return style(&MessageStyle::face_anim, value); } + MessageBuilder& trailing_data(uint16_t value) { + return style(&MessageStyle::trailing_data, value); + } /* Content builder functions */ MessageBuilder& text(std::string_view value) {