From b36708cbedd2a2b1b4c9b8179263411420de905e Mon Sep 17 00:00:00 2001 From: Arkadii Hlushchevskyi Date: Sun, 31 Mar 2024 22:09:09 +0300 Subject: [PATCH] Implemented Global scope for linked forms. --- SPID/include/FormData.h | 11 ++++++++ SPID/include/LinkedDistribution.h | 21 ++++++++------- SPID/src/LinkedDistribution.cpp | 45 ++++++++++++++++++++----------- 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/SPID/include/FormData.h b/SPID/include/FormData.h index ffe2813..1591bb4 100644 --- a/SPID/include/FormData.h +++ b/SPID/include/FormData.h @@ -645,3 +645,14 @@ void Forms::LookupGenericForm(RE::TESDataHandler* const dataHandler, INI::Data& // Likewise, we don't expect plugin names in distributable forms. } } + +inline std::ostream& operator<<(std::ostream& os, Forms::DistributedForm form) +{ + os << form.first; + + if (!form.second.empty()) { + os << " @" << form.second; + } + + return os; +} diff --git a/SPID/include/LinkedDistribution.h b/SPID/include/LinkedDistribution.h index e4a85a2..867b9a1 100644 --- a/SPID/include/LinkedDistribution.h +++ b/SPID/include/LinkedDistribution.h @@ -107,8 +107,8 @@ namespace LinkedDistribution /// /// A set of forms for which distribution sets should be calculated. /// This is typically distributed forms accumulated during first distribution pass. - /// A callback to be called with each DistributionSet. This is supposed to do the actual distribution. - void ForEachLinkedDistributionSet(const DistributedForms& linkedForms, std::function callback); + /// A callback to be called with each DistributionSet. This is supposed to do the actual distribution. + void ForEachLinkedDistributionSet(const DistributedForms& linkedForms, std::function distribute); /// /// Calculates DistributionSet with only DeathItems for each linked form and calls a callback for each of them. @@ -116,12 +116,15 @@ namespace LinkedDistribution /// /// A set of forms for which distribution sets should be calculated. /// This is typically distributed forms accumulated during first distribution pass. - /// A callback to be called with each DistributionSet. This is supposed to do the actual distribution. - void ForEachLinkedDeathDistributionSet(const DistributedForms& linkedForms, std::function callback); + /// A callback to be called with each DistributionSet. This is supposed to do the actual distribution. + void ForEachLinkedDeathDistributionSet(const DistributedForms& linkedForms, std::function distribute); private: template - DataVec
& LinkedFormsForForm(const DistributedForm&, LinkedForms&) const; + DataVec& LinkedFormsForForm(const DistributedForm&, Scope, LinkedForms&) const; + + void ForEachLinkedDistributionSet(const DistributedForms& linkedForms, Scope, std::function distribute); + void ForEachLinkedDeathDistributionSet(const DistributedForms& linkedForms, Scope, std::function distribute); LinkedForms spells{ RECORD::kSpell }; LinkedForms perks{ RECORD::kPerk }; @@ -193,13 +196,14 @@ namespace LinkedDistribution } template - DataVec& Manager::LinkedFormsForForm(const DistributedForm& form, LinkedForms& linkedForms) const + DataVec& Manager::LinkedFormsForForm(const DistributedForm& form, Scope scope, LinkedForms& linkedForms) const { - if (const auto formsIt = linkedForms.forms.find(form.second); formsIt != linkedForms.forms.end()) { + if (const auto formsIt = linkedForms.forms.find(scope == kLocal ? form.second : ""); formsIt != linkedForms.forms.end()) { if (const auto linkedFormsIt = formsIt->second.find(form.first); linkedFormsIt != formsIt->second.end()) { return linkedFormsIt->second; } } + static DataVec empty{}; return empty; } @@ -238,10 +242,9 @@ namespace LinkedDistribution template 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& distributableFormsAtPath = forms[path]; + auto& distributableFormsAtPath = forms[scope == kLocal ? path : ""]; // If item is global, we put it in a common map with no information about the path. auto& distributableForms = distributableFormsAtPath[std::get(linkedForm)]; // Note that we don't use Data.index here, as these linked forms don't have any leveled filters // and as such do not to track their index. diff --git a/SPID/src/LinkedDistribution.cpp b/SPID/src/LinkedDistribution.cpp index ef1cded..df6414f 100644 --- a/SPID/src/LinkedDistribution.cpp +++ b/SPID/src/LinkedDistribution.cpp @@ -207,28 +207,30 @@ namespace LinkedDistribution const auto lastItemIndex = linkedForms.size() - 1; for (int i = 0; i < lastItemIndex; ++i) { const auto& linkedItem = linkedForms[i]; - logger::info("\t├─── {} @{}", describe(linkedItem.first), linkedItem.second); + logger::info("\t├─── {}", describe(linkedItem)); } const auto& lastLinkedItem = linkedForms[lastItemIndex]; - logger::info("\t└─── {} @{}", describe(lastLinkedItem.first), lastLinkedItem.second); + logger::info("\t└─── {}", describe(lastLinkedItem)); } }); } +#pragma endregion - void Manager::ForEachLinkedDistributionSet(const DistributedForms& targetForms, std::function performDistribution) +#pragma region Distribution + void Manager::ForEachLinkedDistributionSet(const DistributedForms& targetForms, Scope scope, std::function performDistribution) { for (const auto& form : targetForms) { - auto& linkedSpells = LinkedFormsForForm(form, spells); - auto& linkedPerks = LinkedFormsForForm(form, perks); - auto& linkedItems = LinkedFormsForForm(form, items); - auto& linkedShouts = LinkedFormsForForm(form, shouts); - auto& linkedLevSpells = LinkedFormsForForm(form, levSpells); - auto& linkedPackages = LinkedFormsForForm(form, packages); - auto& linkedOutfits = LinkedFormsForForm(form, outfits); - auto& linkedKeywords = LinkedFormsForForm(form, keywords); - auto& linkedFactions = LinkedFormsForForm(form, factions); - auto& linkedSleepOutfits = LinkedFormsForForm(form, sleepOutfits); - auto& linkedSkins = LinkedFormsForForm(form, skins); + auto& linkedSpells = LinkedFormsForForm(form, scope, spells); + auto& linkedPerks = LinkedFormsForForm(form, scope, perks); + auto& linkedItems = LinkedFormsForForm(form, scope, items); + auto& linkedShouts = LinkedFormsForForm(form, scope, shouts); + auto& linkedLevSpells = LinkedFormsForForm(form, scope, levSpells); + auto& linkedPackages = LinkedFormsForForm(form, scope, packages); + auto& linkedOutfits = LinkedFormsForForm(form, scope, outfits); + auto& linkedKeywords = LinkedFormsForForm(form, scope, keywords); + auto& linkedFactions = LinkedFormsForForm(form, scope, factions); + auto& linkedSleepOutfits = LinkedFormsForForm(form, scope, sleepOutfits); + auto& linkedSkins = LinkedFormsForForm(form, scope, skins); DistributionSet linkedEntries{ linkedSpells, @@ -253,10 +255,16 @@ namespace LinkedDistribution } } - void Manager::ForEachLinkedDeathDistributionSet(const DistributedForms& targetForms, std::function performDistribution) + void Manager::ForEachLinkedDistributionSet(const DistributedForms& targetForms, std::function performDistribution) + { + ForEachLinkedDistributionSet(targetForms, Scope::kLocal, performDistribution); + ForEachLinkedDistributionSet(targetForms, Scope::kGlobal, performDistribution); + } + + void Manager::ForEachLinkedDeathDistributionSet(const DistributedForms& targetForms, Scope scope, std::function performDistribution) { for (const auto& form : targetForms) { - auto& linkedDeathItems = LinkedFormsForForm(form, deathItems); + auto& linkedDeathItems = LinkedFormsForForm(form, scope, deathItems); DistributionSet linkedEntries{ DistributionSet::empty(), @@ -281,5 +289,10 @@ namespace LinkedDistribution } } + void Manager::ForEachLinkedDeathDistributionSet(const DistributedForms& targetForms, std::function performDistribution) + { + ForEachLinkedDeathDistributionSet(targetForms, Scope::kLocal, performDistribution); + ForEachLinkedDeathDistributionSet(targetForms, Scope::kGlobal, performDistribution); + } #pragma endregion }