Skip to content

Commit

Permalink
Implemented Global scope for linked forms.
Browse files Browse the repository at this point in the history
  • Loading branch information
adya committed Mar 31, 2024
1 parent 6ff3eda commit b36708c
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 25 deletions.
11 changes: 11 additions & 0 deletions SPID/include/FormData.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
21 changes: 12 additions & 9 deletions SPID/include/LinkedDistribution.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,21 +107,24 @@ namespace LinkedDistribution
/// </summary>
/// <param name="linkedForms">A set of forms for which distribution sets should be calculated.
/// This is typically distributed forms accumulated during first distribution pass.</param>
/// <param name="callback">A callback to be called with each DistributionSet. This is supposed to do the actual distribution.</param>
void ForEachLinkedDistributionSet(const DistributedForms& linkedForms, std::function<void(DistributionSet&)> callback);
/// <param name="distribute">A callback to be called with each DistributionSet. This is supposed to do the actual distribution.</param>
void ForEachLinkedDistributionSet(const DistributedForms& linkedForms, std::function<void(DistributionSet&)> distribute);

/// <summary>
/// Calculates DistributionSet with only DeathItems for each linked form and calls a callback for each of them.
/// This method is suitable for distributing items on death.
/// </summary>
/// <param name="linkedForms">A set of forms for which distribution sets should be calculated.
/// This is typically distributed forms accumulated during first distribution pass.</param>
/// <param name="callback">A callback to be called with each DistributionSet. This is supposed to do the actual distribution.</param>
void ForEachLinkedDeathDistributionSet(const DistributedForms& linkedForms, std::function<void(DistributionSet&)> callback);
/// <param name="distribute">A callback to be called with each DistributionSet. This is supposed to do the actual distribution.</param>
void ForEachLinkedDeathDistributionSet(const DistributedForms& linkedForms, std::function<void(DistributionSet&)> distribute);

private:
template <class Form>
DataVec<Form>& LinkedFormsForForm(const DistributedForm&, LinkedForms<Form>&) const;
DataVec<Form>& LinkedFormsForForm(const DistributedForm&, Scope, LinkedForms<Form>&) const;

void ForEachLinkedDistributionSet(const DistributedForms& linkedForms, Scope, std::function<void(DistributionSet&)> distribute);
void ForEachLinkedDeathDistributionSet(const DistributedForms& linkedForms, Scope, std::function<void(DistributionSet&)> distribute);

LinkedForms<RE::SpellItem> spells{ RECORD::kSpell };
LinkedForms<RE::BGSPerk> perks{ RECORD::kPerk };
Expand Down Expand Up @@ -193,13 +196,14 @@ namespace LinkedDistribution
}

template <class Form>
DataVec<Form>& Manager::LinkedFormsForForm(const DistributedForm& form, LinkedForms<Form>& linkedForms) const
DataVec<Form>& Manager::LinkedFormsForForm(const DistributedForm& form, Scope scope, LinkedForms<Form>& 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<Form> empty{};
return empty;
}
Expand Down Expand Up @@ -238,10 +242,9 @@ namespace LinkedDistribution
template <class Form>
void LinkedForms<Form>::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<RE::TESForm*>(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<RE::TESForm*>(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.
Expand Down
45 changes: 29 additions & 16 deletions SPID/src/LinkedDistribution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<void(DistributionSet&)> performDistribution)
#pragma region Distribution
void Manager::ForEachLinkedDistributionSet(const DistributedForms& targetForms, Scope scope, std::function<void(DistributionSet&)> 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,
Expand All @@ -253,10 +255,16 @@ namespace LinkedDistribution
}
}

void Manager::ForEachLinkedDeathDistributionSet(const DistributedForms& targetForms, std::function<void(DistributionSet&)> performDistribution)
void Manager::ForEachLinkedDistributionSet(const DistributedForms& targetForms, std::function<void(DistributionSet&)> performDistribution)
{
ForEachLinkedDistributionSet(targetForms, Scope::kLocal, performDistribution);
ForEachLinkedDistributionSet(targetForms, Scope::kGlobal, performDistribution);
}

void Manager::ForEachLinkedDeathDistributionSet(const DistributedForms& targetForms, Scope scope, std::function<void(DistributionSet&)> performDistribution)
{
for (const auto& form : targetForms) {
auto& linkedDeathItems = LinkedFormsForForm(form, deathItems);
auto& linkedDeathItems = LinkedFormsForForm(form, scope, deathItems);

DistributionSet linkedEntries{
DistributionSet::empty<RE::SpellItem>(),
Expand All @@ -281,5 +289,10 @@ namespace LinkedDistribution
}
}

void Manager::ForEachLinkedDeathDistributionSet(const DistributedForms& targetForms, std::function<void(DistributionSet&)> performDistribution)
{
ForEachLinkedDeathDistributionSet(targetForms, Scope::kLocal, performDistribution);
ForEachLinkedDeathDistributionSet(targetForms, Scope::kGlobal, performDistribution);
}
#pragma endregion
}

0 comments on commit b36708c

Please sign in to comment.