mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-20 21:33:28 -04:00
update data for flow node usage
This commit is contained in:
@@ -873,7 +873,7 @@ void randomizer_checkAndOverrideEntranceData(const char*& stageName, s8& roomNo,
|
||||
}
|
||||
}
|
||||
|
||||
static void randomizer_setTempFlag(RandomizerContext::itemLocationData data) {
|
||||
void randomizer_setTempFlag(RandomizerContext::itemLocationData data) {
|
||||
// If stage is 0xFF, then this is an event flag
|
||||
if (data.stage == 0xFF) {
|
||||
g_randomizerState.mTrackerTempEventFlag = data.flag;
|
||||
@@ -1113,6 +1113,50 @@ static std::array<u8, 20> CreateAttributeData(const YAML::Node& node, const std:
|
||||
RandomizerContext WriteSeedData(randomizer::logic::world::World* world) {
|
||||
RandomizerContext randoData{};
|
||||
|
||||
// Give custom flows and messages new indices as we read them in/create them
|
||||
std::unordered_map<std::string, u16> customMessageIDs{};
|
||||
std::unordered_map<std::string, u16> customFlowIDs{};
|
||||
std::unordered_set<u16> usedMessageIDs{};
|
||||
std::unordered_set<u16> usedFlowIDs{};
|
||||
u16 curCustomMessageID = BASE_CUSTOM_MSG_AND_FLOW_ID;
|
||||
u16 curCustomFlowID = BASE_CUSTOM_MSG_AND_FLOW_ID;
|
||||
|
||||
// Helper functions for assigning new custom flow IDs/message IDs
|
||||
auto handleCustomID = [](const std::string& name, auto& customIds, auto& usedIds, u16& curCustomID) {
|
||||
u16 resultIndex{};
|
||||
// Check to see if we're setting a custom index
|
||||
auto resultInt = randomizer::utility::str::toInt(name);
|
||||
// If we have a regular index, then use that directly
|
||||
if (resultInt.has_value()) {
|
||||
resultIndex = resultInt.value();
|
||||
} else {
|
||||
// If we don't, assume we're setting the index as custom
|
||||
if (customIds.contains(name)) {
|
||||
resultIndex = customIds[name];
|
||||
} else {
|
||||
while (usedIds.contains(curCustomID)) {
|
||||
++curCustomID;
|
||||
}
|
||||
auto newIndex = curCustomID++;
|
||||
resultIndex = newIndex;
|
||||
customIds[name] = newIndex;
|
||||
}
|
||||
}
|
||||
|
||||
usedIds.insert(resultIndex);
|
||||
return resultIndex;
|
||||
};
|
||||
|
||||
|
||||
auto handleCustomFlowID = [&](const std::string& name) {
|
||||
return handleCustomID(name, customFlowIDs, usedFlowIDs, curCustomFlowID);
|
||||
};
|
||||
|
||||
|
||||
auto handleCustomMessageID = [&](const std::string& name) {
|
||||
return handleCustomID(name, customMessageIDs, usedMessageIDs, curCustomMessageID);
|
||||
};
|
||||
|
||||
// Settings we need to check ingame
|
||||
for (const auto& [setting, info] : *randomizer::seedgen::settings::GetAllSettingsInfo()) {
|
||||
if (info->NeedInGame()) {
|
||||
@@ -1254,6 +1298,60 @@ RandomizerContext WriteSeedData(randomizer::logic::world::World* world) {
|
||||
}
|
||||
}
|
||||
|
||||
// Items that are given by FLW events. Override the item in the existing event with the
|
||||
// randomized item
|
||||
if (location->HasCategories("FLW Event")) {
|
||||
for (const auto& flwEventNode : metaData["FLW Event"]) {
|
||||
u8 group = flwEventNode["Group"].as<u8>();
|
||||
u16 index = handleCustomFlowID(flwEventNode["Index"].as<std::string>());
|
||||
mesg_flow_node_event event{};
|
||||
event.type = 3; // event type node
|
||||
event.event_idx = 8;
|
||||
event.next_node_idx = handleCustomFlowID(flwEventNode["Next Node Index"].as<std::string>());
|
||||
auto params = flwEventNode["Parameters"].as<u32>();
|
||||
// Zero out the spot for the item id
|
||||
params &= 0xFFFFFF00;
|
||||
// Put in the item id
|
||||
params |= location->GetCurrentItem()->GetID();
|
||||
// Set the params in the correct order
|
||||
event.params[0] = (params >> 24) & 0xFF;
|
||||
event.params[1] = (params >> 16) & 0xFF;
|
||||
event.params[2] = (params >> 8) & 0xFF;
|
||||
event.params[3] = params & 0xFF;
|
||||
|
||||
// Construct another FLW node to set the associated flag in a temporary variable
|
||||
// right before we receive the item. This ensures that a tracker/AP can pick up
|
||||
// on the fact that we've received the item.
|
||||
auto newFlwIndex = handleCustomFlowID(location->GetName() + " Flag Set Node");
|
||||
mesg_flow_node_event flagEvent{};
|
||||
flagEvent.type = 3; // event type node
|
||||
flagEvent.event_idx = 46; // Set temporary randomizer flag
|
||||
|
||||
u8 stage{0xFF};
|
||||
u16 flag{0xFFFF};
|
||||
if (metaData["Event Flag"]) {
|
||||
flag = metaData["Event Flag"].as<u16>();
|
||||
} else if (metaData["Switch Flag"]) {
|
||||
stage = metaData["Switch Flag"]["Stage"].as<u8>();
|
||||
flag = metaData["Switch Flag"]["Flag"].as<u8>();
|
||||
}
|
||||
flagEvent.params[0] = 0;
|
||||
flagEvent.params[1] = stage;
|
||||
flagEvent.params[2] = (flag >> 8) & 0xFF;
|
||||
flagEvent.params[3] = flag & 0xFF;
|
||||
|
||||
// Store the modified FLW nodes. The flag event takes the place of the original
|
||||
// index we're modifying and then leads into the custom index of the event that
|
||||
// sets up the item id
|
||||
flagEvent.next_node_idx = newFlwIndex;
|
||||
u32 key = (group << 16) | index;
|
||||
randoData.mFlowPatches[key] = std::bit_cast<u64>(flagEvent);
|
||||
|
||||
key = (CUSTOM_BMG_GROUP << 16) | newFlwIndex;
|
||||
randoData.mFlowPatches[key] = std::bit_cast<u64>(event);
|
||||
}
|
||||
}
|
||||
|
||||
// Items that we lookup just by calling their location name
|
||||
if (location->HasCategories("Name Lookup")) {
|
||||
for (const auto& locationNameNode : metaData["Name Lookup"]) {
|
||||
@@ -1280,7 +1378,6 @@ RandomizerContext WriteSeedData(randomizer::logic::world::World* world) {
|
||||
} else if (flagNode.IsMap()) {
|
||||
const auto& condition = flagNode.begin()->first.as<std::string>();
|
||||
if (world->EvaluateSettingCondition(condition)) {
|
||||
randomizer::session::LogDebug(fmt::format("Setting flags for {}", condition).c_str());
|
||||
for (const auto& conditionalFlag : flagNode.begin()->second) {
|
||||
const auto& flag = conditionalFlag.as<u16>();
|
||||
randoData.mStartEventFlags.push_back(flag);
|
||||
@@ -1294,7 +1391,6 @@ RandomizerContext WriteSeedData(randomizer::logic::world::World* world) {
|
||||
const auto& region = regionNode.first.as<std::string>();
|
||||
const auto& index = regionNode.second["Index"].as<int>();
|
||||
const auto& flags = regionNode.second["Flags"];
|
||||
randomizer::session::LogDebug(fmt::format("Setting region flags for {}", region).c_str());
|
||||
// This seems kinda scuffed so maybe we change it later
|
||||
for (const auto& flagNode : flags) {
|
||||
if (flagNode.IsScalar()) {
|
||||
@@ -1400,49 +1496,6 @@ RandomizerContext WriteSeedData(randomizer::logic::world::World* world) {
|
||||
}
|
||||
}
|
||||
|
||||
// Give custom flows and messages new indices as we read them in
|
||||
std::unordered_map<std::string, u16> customMessageIDs{};
|
||||
std::unordered_map<std::string, u16> customFlowIDs{};
|
||||
std::unordered_set<u16> usedMessageIDs{};
|
||||
std::unordered_set<u16> usedFlowIDs{};
|
||||
u16 curCustomMessageID = BASE_CUSTOM_MSG_AND_FLOW_ID;
|
||||
u16 curCustomFlowID = BASE_CUSTOM_MSG_AND_FLOW_ID;
|
||||
|
||||
// Helper functions for assigning new custom flow IDs/message IDs
|
||||
auto handleCustomID = [](const YAML::Node& node, auto& customIds, auto& usedIds, u16& curCustomID) {
|
||||
u16 resultIndex{};
|
||||
// Check to see if we're setting a custom index
|
||||
auto resultStr = node.as<std::string>();
|
||||
auto resultInt = randomizer::utility::str::toInt(resultStr);
|
||||
// If we have a regular index, then use that directly
|
||||
if (resultInt.has_value()) {
|
||||
resultIndex = resultInt.value();
|
||||
} else {
|
||||
// If we don't, assume we're setting the index as custom
|
||||
if (customIds.contains(resultStr)) {
|
||||
resultIndex = customIds[resultStr];
|
||||
} else {
|
||||
while (usedIds.contains(curCustomID)) {
|
||||
++curCustomID;
|
||||
}
|
||||
auto newIndex = curCustomID++;
|
||||
resultIndex = newIndex;
|
||||
customIds[resultStr] = newIndex;
|
||||
}
|
||||
}
|
||||
|
||||
usedIds.insert(resultIndex);
|
||||
return resultIndex;
|
||||
};
|
||||
|
||||
auto handleCustomFlowID = [&](const YAML::Node& node) {
|
||||
return handleCustomID(node, customFlowIDs, usedFlowIDs, curCustomFlowID);
|
||||
};
|
||||
|
||||
auto handleCustomMessageID = [&](const YAML::Node& node) {
|
||||
return handleCustomID(node, customMessageIDs, usedMessageIDs, curCustomMessageID);
|
||||
};
|
||||
|
||||
// Flow Patches
|
||||
auto flowPatches = LOAD_EMBED_YAML(RANDO_DATA_PATH "flow_patches.yaml");
|
||||
for (const auto& groupNode : flowPatches) {
|
||||
@@ -1476,7 +1529,7 @@ RandomizerContext WriteSeedData(randomizer::logic::world::World* world) {
|
||||
}
|
||||
} else {
|
||||
name = flowNode["name"].as<std::string>();
|
||||
indices.push_back(handleCustomFlowID(flowNode["name"]));
|
||||
indices.push_back(handleCustomFlowID(flowNode["name"].as<std::string>()));
|
||||
}
|
||||
|
||||
const auto& type = flowNode["type"].as<std::string>();
|
||||
@@ -1496,7 +1549,7 @@ RandomizerContext WriteSeedData(randomizer::logic::world::World* world) {
|
||||
"do not match num results. (expected: {}. size: {})", name, branch->field_0x1, results.size()));
|
||||
}
|
||||
for (const auto& resultNode : results) {
|
||||
auto resultIndex = handleCustomFlowID(resultNode);
|
||||
auto resultIndex = handleCustomFlowID(resultNode.as<std::string>());
|
||||
for (auto index : indices) {
|
||||
u32 key = (groupNo << 16) | index;
|
||||
randoData.mFlowPatchesBranchOverrides[key].push_back(resultIndex);
|
||||
@@ -1508,7 +1561,7 @@ RandomizerContext WriteSeedData(randomizer::logic::world::World* world) {
|
||||
auto event = reinterpret_cast<mesg_flow_node_event*>(&value);
|
||||
event->type = 3;
|
||||
event->event_idx = flowNode["event"].as<u8>();
|
||||
event->next_node_idx = handleCustomFlowID(flowNode["next node index"]);
|
||||
event->next_node_idx = handleCustomFlowID(flowNode["next node index"].as<std::string>());
|
||||
u32 params = flowNode["parameters"].as<u32>();
|
||||
event->params[0] = (params >> 24) & 0xFF;
|
||||
event->params[1] = (params >> 16) & 0xFF;
|
||||
@@ -1517,8 +1570,8 @@ RandomizerContext WriteSeedData(randomizer::logic::world::World* world) {
|
||||
} else if (type == "message") {
|
||||
auto message = reinterpret_cast<mesg_flow_node*>(&value);
|
||||
message->type = 1;
|
||||
message->msg_index = handleCustomMessageID(flowNode["inf index"]);
|
||||
message->next_node_idx = handleCustomFlowID(flowNode["next flow index"]);
|
||||
message->msg_index = handleCustomMessageID(flowNode["inf index"].as<std::string>());
|
||||
message->next_node_idx = handleCustomFlowID(flowNode["next flow index"].as<std::string>());
|
||||
|
||||
// If a custom message is too long, split it up among additional flow/message nodes
|
||||
if (message->msg_index >= BASE_CUSTOM_MSG_AND_FLOW_ID) {
|
||||
@@ -1548,13 +1601,9 @@ RandomizerContext WriteSeedData(randomizer::logic::world::World* world) {
|
||||
auto extraTextName = textName + std::to_string(i + 1);
|
||||
world->AddNewText(extraTextName) = extraText[i];
|
||||
|
||||
// Kinda silly, but means we don't need to create another function
|
||||
// to handle direct string names.
|
||||
YAML::Node node{};
|
||||
node["name"] = extraTextName;
|
||||
// Create new Flow and Message Ids for the split text object
|
||||
auto newCustomFlowIndex = handleCustomFlowID(node["name"]);
|
||||
auto newCustomMessageIndex = handleCustomMessageID(node["name"]);
|
||||
auto newCustomFlowIndex = handleCustomFlowID(extraTextName);
|
||||
auto newCustomMessageIndex = handleCustomMessageID(extraTextName);
|
||||
|
||||
// Create the new flow node. We're storing its own flow index with
|
||||
// itself for now, but we'll shift it back to the previous node later
|
||||
@@ -1629,7 +1678,7 @@ RandomizerContext WriteSeedData(randomizer::logic::world::World* world) {
|
||||
messageId = overrideNode["Message Id"].as<u16>();
|
||||
} else {
|
||||
// If no message id specified, assume a custom one
|
||||
messageId = handleCustomMessageID(overrideNode["Name"]);
|
||||
messageId = handleCustomMessageID(overrideNode["Name"].as<std::string>());
|
||||
}
|
||||
u32 key = (group << 16) | messageId;
|
||||
for (auto language : randomizer::supportedLanguages) {
|
||||
|
||||
@@ -222,6 +222,8 @@ void randomizer_checkAndOverrideEntranceData(const char*& i_Name, s8& i_RoomNo,
|
||||
* variable. This allows the tracker/Archipelago to know a location has been checked
|
||||
* when the item is received instead of some indeterminate amount of time afterward.
|
||||
*/
|
||||
void randomizer_setTempFlag(RandomizerContext::itemLocationData);
|
||||
|
||||
void randomizer_setTempFlagForLocation(const std::string& locationName);
|
||||
|
||||
void randomizer_setTempFlagForFLWOverride(u32 key);
|
||||
|
||||
Reference in New Issue
Block a user