Skip to content

Commit

Permalink
Introduced 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 d2f9688 commit bb018e2
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 15 deletions.
28 changes: 24 additions & 4 deletions SPID/include/LinkedDistribution.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,31 @@

namespace LinkedDistribution
{

/// <summary>
/// Scope of a linked form determines which distributions can trigger linked forms.
/// </summary>
enum Scope : std::uint8_t
{
/// <summary>
/// Local scope links forms only to distributions defined in the same configuration file.
/// </summary>
kLocal = 0,

/// <summary>
/// Global scope links forms to all distributions in all loaded configuration files.
/// </summary>
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<FormOrEditorID> formIDs{};

Expand Down Expand Up @@ -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<Manager>
Expand Down Expand Up @@ -206,17 +225,18 @@ namespace LinkedDistribution
{
for (auto& rawForm : rawLinkedForms) {
auto form = detail::LookupLinkedForm<Form>(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 <class Form>
void LinkedForms<Form>::Link(Form* form, const FormVec& linkedForms, const IndexOrCount& idxOrCount, const PercentChance& chance, const Path& path)
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& distributableForms = forms[std::get<RE::TESForm*>(linkedForm)];
Expand Down
33 changes: 22 additions & 11 deletions SPID/src/LinkedDistribution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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<RE::BGSKeyword>(); keyword) {
keywords.Link(keyword, parentForms, idxOrCount, chance, path);
keywords.Link(keyword, scope, parentForms, idxOrCount, chance, path);
} else if (const auto spell = form->As<RE::SpellItem>(); spell) {
spells.Link(spell, parentForms, idxOrCount, chance, path);
spells.Link(spell, scope, parentForms, idxOrCount, chance, path);
} else if (const auto perk = form->As<RE::BGSPerk>(); perk) {
perks.Link(perk, parentForms, idxOrCount, chance, path);
perks.Link(perk, scope, parentForms, idxOrCount, chance, path);
} else if (const auto shout = form->As<RE::TESShout>(); shout) {
shouts.Link(shout, parentForms, idxOrCount, chance, path);
shouts.Link(shout, scope, parentForms, idxOrCount, chance, path);
} else if (const auto item = form->As<RE::TESBoundObject>(); item) {
items.Link(item, parentForms, idxOrCount, chance, path);
items.Link(item, scope, parentForms, idxOrCount, chance, path);
} else if (const auto outfit = form->As<RE::BGSOutfit>(); outfit) {
outfits.Link(outfit, parentForms, idxOrCount, chance, path);
outfits.Link(outfit, scope, parentForms, idxOrCount, chance, path);
} else if (const auto faction = form->As<RE::TESFaction>(); faction) {
factions.Link(faction, parentForms, idxOrCount, chance, path);
factions.Link(faction, scope, parentForms, idxOrCount, chance, path);
} else if (const auto skin = form->As<RE::TESObjectARMO>(); 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) {
Expand All @@ -142,7 +153,7 @@ namespace LinkedDistribution
} else {
packageIndex = std::get<Index>(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));
}
Expand Down

0 comments on commit bb018e2

Please sign in to comment.