From bb018e231123d21939d5af5411710dcfaf5d67f6 Mon Sep 17 00:00:00 2001 From: Arkadii Hlushchevskyi Date: Sun, 31 Mar 2024 02:01:34 +0200 Subject: [PATCH] Introduced Scope for linked forms. --- SPID/include/LinkedDistribution.h | 28 ++++++++++++++++++++++---- SPID/src/LinkedDistribution.cpp | 33 ++++++++++++++++++++----------- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/SPID/include/LinkedDistribution.h b/SPID/include/LinkedDistribution.h index a5eeb18..4c3b544 100644 --- a/SPID/include/LinkedDistribution.h +++ b/SPID/include/LinkedDistribution.h @@ -5,12 +5,31 @@ namespace LinkedDistribution { + + /// + /// Scope of a linked form determines which distributions can trigger linked forms. + /// + enum Scope : std::uint8_t + { + /// + /// Local scope links forms only to distributions defined in the same configuration file. + /// + kLocal = 0, + + /// + /// Global scope links forms to all distributions in all loaded configuration files. + /// + kGlobal + }; + namespace INI { struct RawLinkedForm { FormOrEditorID formOrEditorID{}; + Scope scope{ kLocal }; + /// Raw filters in RawLinkedForm only use MATCH, there is no meaning for ALL or NOT, so they are ignored. Filters formIDs{}; @@ -66,7 +85,7 @@ namespace LinkedDistribution RECORD::TYPE type; FormsMap forms{}; - void Link(Form*, const FormVec& linkedForms, const IndexOrCount&, const PercentChance&, const Path&); + void Link(Form*, Scope, const FormVec& linkedForms, const IndexOrCount&, const PercentChance&, const Path&); }; class Manager : public ISingleton @@ -206,17 +225,18 @@ namespace LinkedDistribution { for (auto& rawForm : rawLinkedForms) { auto form = detail::LookupLinkedForm
(dataHandler, rawForm); - auto& [formID, parentFormIDs, count, chance, path] = rawForm; + auto& [formID, scope, parentFormIDs, count, chance, path] = rawForm; FormVec parentForms{}; if (Forms::detail::formID_to_form(dataHandler, parentFormIDs.MATCH, parentForms, path, false, false)) { - Link(form, parentForms, count, chance, path); + Link(form, scope, parentForms, count, chance, path); } } } template - void LinkedForms::Link(Form* form, const FormVec& linkedForms, const IndexOrCount& idxOrCount, const PercentChance& chance, const Path& path) + void LinkedForms::Link(Form* form, Scope scope, const FormVec& linkedForms, const IndexOrCount& idxOrCount, const PercentChance& chance, const Path& path) { + // TODO: Handle scope for (const auto& linkedForm : linkedForms) { if (std::holds_alternative(linkedForm)) { auto& distributableForms = forms[std::get(linkedForm)]; diff --git a/SPID/src/LinkedDistribution.cpp b/SPID/src/LinkedDistribution.cpp index 00a6e38..1374aff 100644 --- a/SPID/src/LinkedDistribution.cpp +++ b/SPID/src/LinkedDistribution.cpp @@ -21,14 +21,24 @@ namespace LinkedDistribution kRequired = kLinkedForms }; - bool TryParse(const std::string& key, const std::string& value, const Path& path) + bool TryParse(const std::string& originalKey, const std::string& value, const Path& path) { + std::string key = originalKey; + + Scope scope = kLocal; + + if (key.starts_with("Global"sv)) { + scope = kGlobal; + key.erase(0, 6); + } + if (!key.starts_with("Linked"sv)) { return false; } std::string rawType = key.substr(6); auto type = RECORD::GetType(rawType); + if (type == RECORD::kTotal) { logger::warn("IGNORED: Unsupported Linked Form type: {}"sv, rawType); return true; @@ -51,6 +61,7 @@ namespace LinkedDistribution INI::RawLinkedForm item{}; item.formOrEditorID = distribution::get_record(sections[kForm]); + item.scope = scope; item.path = path; for (auto& IDs : split_IDs) { @@ -106,28 +117,28 @@ namespace LinkedDistribution auto& genericForms = rawLinkedForms[RECORD::kForm]; for (auto& rawForm : genericForms) { if (auto form = detail::LookupLinkedForm(dataHandler, rawForm); form) { - auto& [formID, parentFormIDs, idxOrCount, chance, path] = rawForm; + auto& [formID, scope, parentFormIDs, idxOrCount, chance, path] = rawForm; FormVec parentForms{}; if (!Forms::detail::formID_to_form(dataHandler, parentFormIDs.MATCH, parentForms, path, false, false)) { continue; } // Add to appropriate list. (Note that type inferring doesn't recognize SleepOutfit or DeathItems) if (const auto keyword = form->As(); keyword) { - keywords.Link(keyword, parentForms, idxOrCount, chance, path); + keywords.Link(keyword, scope, parentForms, idxOrCount, chance, path); } else if (const auto spell = form->As(); spell) { - spells.Link(spell, parentForms, idxOrCount, chance, path); + spells.Link(spell, scope, parentForms, idxOrCount, chance, path); } else if (const auto perk = form->As(); perk) { - perks.Link(perk, parentForms, idxOrCount, chance, path); + perks.Link(perk, scope, parentForms, idxOrCount, chance, path); } else if (const auto shout = form->As(); shout) { - shouts.Link(shout, parentForms, idxOrCount, chance, path); + shouts.Link(shout, scope, parentForms, idxOrCount, chance, path); } else if (const auto item = form->As(); item) { - items.Link(item, parentForms, idxOrCount, chance, path); + items.Link(item, scope, parentForms, idxOrCount, chance, path); } else if (const auto outfit = form->As(); outfit) { - outfits.Link(outfit, parentForms, idxOrCount, chance, path); + outfits.Link(outfit, scope, parentForms, idxOrCount, chance, path); } else if (const auto faction = form->As(); faction) { - factions.Link(faction, parentForms, idxOrCount, chance, path); + factions.Link(faction, scope, parentForms, idxOrCount, chance, path); } else if (const auto skin = form->As(); skin) { - skins.Link(skin, parentForms, idxOrCount, chance, path); + skins.Link(skin, scope, parentForms, idxOrCount, chance, path); } else { auto type = form->GetFormType(); if (type == RE::FormType::Package || type == RE::FormType::FormList) { @@ -142,7 +153,7 @@ namespace LinkedDistribution } else { packageIndex = std::get(idxOrCount); } - packages.Link(form, parentForms, packageIndex, chance, path); + packages.Link(form, scope, parentForms, packageIndex, chance, path); } else { logger::warn("\t[{}] Unsupported Form type: {}", path, RE::FormTypeToString(type)); }