From 9fc90379607a497145e04029e4e179b4e755b31e Mon Sep 17 00:00:00 2001 From: MetricExpansion <> Date: Tue, 18 Oct 2022 21:25:58 -0700 Subject: [PATCH] More cleanup --- include/ArmorAddonOverrideService.h | 3 +- include/RE/REAugments.h | 4 +- src/ArmorAddonOverrideService.cpp | 138 ++++++++++++++-------------- src/OutfitSystem.cpp | 6 +- 4 files changed, 74 insertions(+), 77 deletions(-) diff --git a/include/ArmorAddonOverrideService.h b/include/ArmorAddonOverrideService.h index 83668a0..3a2ec75 100644 --- a/include/ArmorAddonOverrideService.h +++ b/include/ArmorAddonOverrideService.h @@ -75,10 +75,9 @@ struct Outfit { bool hasShield() const; std::unordered_set computeDisplaySet(const std::unordered_set& equippedSet); - SlotPolicy::Mode effectivePolicyForSlot(RE::BIPED_OBJECT slot); void setSlotPolicy(RE::BIPED_OBJECT slot, std::optional policy); + void setBlanketSlotPolicy(SlotPolicy::Mode policy); void setDefaultSlotPolicy(); - void setAllSlotPolicy(SlotPolicy::Mode policy); void load(const proto::Outfit& proto, const SKSE::SerializationInterface*); void load_legacy(const SKSE::SerializationInterface* intfc, std::uint32_t version);// can throw ArmorAddonOverrideService::load_error diff --git a/include/RE/REAugments.h b/include/RE/REAugments.h index 5b8320a..80823a7 100644 --- a/include/RE/REAugments.h +++ b/include/RE/REAugments.h @@ -53,8 +53,8 @@ namespace RE { }// namespace TESObjectARMOAugments namespace BIPED_OBJECTS_META { - inline constexpr std::uint32_t firstSlot = RE::BIPED_OBJECTS::kHead; - inline constexpr std::uint32_t numSlots = RE::BIPED_OBJECTS::kEditorTotal; + inline constexpr std::uint32_t kFirstSlot = RE::BIPED_OBJECTS::kHead; + inline constexpr std::uint32_t kNumSlots = RE::BIPED_OBJECTS::kEditorTotal; }// namespace BIPED_OBJECTS_META }// namespace RE diff --git a/src/ArmorAddonOverrideService.cpp b/src/ArmorAddonOverrideService.cpp index a495f12..be11478 100644 --- a/src/ArmorAddonOverrideService.cpp +++ b/src/ArmorAddonOverrideService.cpp @@ -36,28 +36,14 @@ bool Outfit::hasShield() const { return false; }; -SlotPolicy::Mode Outfit::effectivePolicyForSlot(RE::BIPED_OBJECT slot) { - auto policy = slotPolicies.find(slot); - if (policy != slotPolicies.end()) return policy->second; - return slotPolicy; -} - void Outfit::setDefaultSlotPolicy() { slotPolicies.clear(); slotPolicies[RE::BIPED_OBJECTS::kShield] = SlotPolicy::Mode::XEXO; slotPolicy = SlotPolicy::Mode::XXOO; } -void Outfit::setAllSlotPolicy(SlotPolicy::Mode preference) { - if (preference >= SlotPolicy::Mode::MAX) { - LOG(err, "Invalid slot preference {}.", preference); - return; - } - slotPolicy = preference; -} - void Outfit::setSlotPolicy(RE::BIPED_OBJECT slot, std::optional policy) { - if (slot >= RE::BIPED_OBJECTS_META::numSlots) { + if (slot >= RE::BIPED_OBJECTS_META::kNumSlots) { LOG(err, "Invalid slot {}.", static_cast(slot)); return; } @@ -72,30 +58,41 @@ void Outfit::setSlotPolicy(RE::BIPED_OBJECT slot, std::optional= SlotPolicy::Mode::MAX) { + LOG(err, "Invalid slot preference {}.", policy); + return; + } + slotPolicy = policy; +} + std::unordered_set Outfit::computeDisplaySet(const std::unordered_set& equippedSet) { - std::unordered_set result; - - std::array equipped{nullptr}; - std::array outfit{nullptr}; - std::uint32_t occupiedMask = 0; + // Helper function that assigns the armor's to the positions in an array that match the armor's slot mask. + auto assignToMatchingSlots = [](std::array& dest, RE::TESObjectARMO* armor) { + auto mask = static_cast(armor->GetSlotMask()); + for (auto slot = RE::BIPED_OBJECTS_META::kFirstSlot; slot < RE::BIPED_OBJECTS_META::kNumSlots; slot++) { + if (mask & (1 << slot)) dest[slot] = armor; + } + }; + // Get the list with the equipped armor in each slot + std::array equipped{nullptr}; for (auto armor : equippedSet) { if (!armor) continue; - auto mask = static_cast(armor->GetSlotMask()); - for (auto slot = RE::BIPED_OBJECTS_META::firstSlot; slot < RE::BIPED_OBJECTS_META::numSlots; slot++) { - if (mask & (1 << slot)) equipped[slot] = armor; - } + assignToMatchingSlots(equipped, armor); } + // Get the list with the outfit armor in each slot + std::array outfit{nullptr}; for (auto armor : armors) { if (!armor) continue; - auto mask = static_cast(armor->GetSlotMask()); - for (auto slot = RE::BIPED_OBJECTS_META::firstSlot; slot < RE::BIPED_OBJECTS_META::numSlots; slot++) { - if (mask & (1 << slot)) outfit[slot] = armor; - } + assignToMatchingSlots(outfit, armor); } - for (auto slot = RE::BIPED_OBJECTS_META::firstSlot; slot < RE::BIPED_OBJECTS_META::numSlots; slot++) { + // Go pairwise through the two lists and select what goes in the results slot + std::unordered_set result; + std::uint32_t occupiedMask = 0; + for (auto slot = RE::BIPED_OBJECTS_META::kFirstSlot; slot < RE::BIPED_OBJECTS_META::kNumSlots; slot++) { // Someone before us already got this slot. if (occupiedMask & (1 << slot)) continue; // Select the slot's policy, falling back to the outfit's policy if none. @@ -105,14 +102,14 @@ std::unordered_set Outfit::computeDisplaySet(const std::unor auto selection = SlotPolicy::select(preference, equipped[slot], outfit[slot]); RE::TESObjectARMO* selectedArmor = nullptr; switch (selection) { - case SlotPolicy::Selection::EMPTY: - break; case SlotPolicy::Selection::EQUIPPED: selectedArmor = equipped[slot]; break; case SlotPolicy::Selection::OUTFIT: selectedArmor = outfit[slot]; break; + case SlotPolicy::Selection::EMPTY: + break; } if (!selectedArmor) continue; occupiedMask |= static_cast(selectedArmor->GetSlotMask()); @@ -157,7 +154,7 @@ void Outfit::load(const proto::Outfit& proto, const SKSE::SerializationInterface for (const auto& pair : proto.slot_policies()) { auto slot = static_cast(pair.first); auto policy = static_cast(pair.second); - if (slot >= RE::BIPED_OBJECTS_META::numSlots) { + if (slot >= RE::BIPED_OBJECTS_META::kNumSlots) { LOG(err, "Invalid slot {}.", static_cast(slot)); continue; } @@ -588,44 +585,45 @@ void ArmorAddonOverrideService::dump() const { LOG(info, "All state has been dumped."); } -// Negative values mean "advanced option" -std::array SlotPolicy::g_policiesMetadata = { - SlotPolicy::Metadata{"XXXX", 100, true}, // Never show anything - SlotPolicy::Metadata{"XXXE", 101, true}, // If outfit and equipped, show equipped - SlotPolicy::Metadata{"XXXO", 2, false}, // If outfit and equipped, show outfit (require equipped, no passthrough) - SlotPolicy::Metadata{"XXOX", 102, true}, // If only outfit, show outfit - SlotPolicy::Metadata{"XXOE", 103, true}, // If only outfit, show outfit. If both, show equipped - SlotPolicy::Metadata{"XXOO", 1, false}, // If outfit, show outfit (always show outfit, no passthough) - SlotPolicy::Metadata{"XEXX", 104, true}, // If only equipped, show equipped - SlotPolicy::Metadata{"XEXE", 105, true}, // If equipped, show equipped - SlotPolicy::Metadata{"XEXO", 3, false}, // If only equipped, show equipped. If both, show outfit - SlotPolicy::Metadata{"XEOX", 106, true}, // If only equipped, show equipped. If only outfit, show outfit - SlotPolicy::Metadata{"XEOE", 107, true}, // If only equipped, show equipped. If only outfit, show outfit. If both, show equipped - SlotPolicy::Metadata{"XEOO", 108, true} // If only equipped, show equipped. If only outfit, show outfit. If both, show outfit -}; +namespace SlotPolicy { + // Negative values mean "advanced option" + std::array g_policiesMetadata = { + Metadata{"XXXX", 100, true}, // Never show anything + Metadata{"XXXE", 101, true}, // If outfit and equipped, show equipped + Metadata{"XXXO", 2, false}, // If outfit and equipped, show outfit (require equipped, no passthrough) + Metadata{"XXOX", 102, true}, // If only outfit, show outfit + Metadata{"XXOE", 103, true}, // If only outfit, show outfit. If both, show equipped + Metadata{"XXOO", 1, false}, // If outfit, show outfit (always show outfit, no passthough) + Metadata{"XEXX", 104, true}, // If only equipped, show equipped + Metadata{"XEXE", 105, true}, // If equipped, show equipped + Metadata{"XEXO", 3, false}, // If only equipped, show equipped. If both, show outfit + Metadata{"XEOX", 106, true}, // If only equipped, show equipped. If only outfit, show outfit + Metadata{"XEOE", 107, true}, // If only equipped, show equipped. If only outfit, show outfit. If both, show equipped + Metadata{"XEOO", 108, true} // If only equipped, show equipped. If only outfit, show outfit. If both, show outfit + }; -SlotPolicy::Selection SlotPolicy::select(SlotPolicy::Mode policy, bool hasEquipped, bool hasOutfit) { - if (policy >= Mode::MAX) { - LOG(err, "Invalid slot preference {}", policy); - policy = Mode::XXXX; - } - char out = 'X'; - if (!hasEquipped && !hasOutfit) { - out = g_policiesMetadata[policy].code[0]; - } else if (hasEquipped && !hasOutfit) { - out = g_policiesMetadata[policy].code[1]; - } else if (!hasEquipped && hasOutfit) { - out = g_policiesMetadata[policy].code[2]; - } else if (hasEquipped && hasOutfit) { - out = g_policiesMetadata[policy].code[3]; - } - if (out == 'X') { - return SlotPolicy::Selection::EMPTY; - } else if (out == 'E') { - return SlotPolicy::Selection::EQUIPPED; - } else if (out == 'O') { - return SlotPolicy::Selection::OUTFIT; - } else { - return SlotPolicy::Selection::EMPTY; + Selection select(Mode policy, bool hasEquipped, bool hasOutfit) { + if (policy >= Mode::MAX) { + LOG(err, "Invalid slot preference {}", policy); + policy = Mode::XXXX; + } + char out; + if (!hasEquipped && !hasOutfit) { + out = g_policiesMetadata[policy].code[0]; + } else if (hasEquipped && !hasOutfit) { + out = g_policiesMetadata[policy].code[1]; + } else if (!hasEquipped && hasOutfit) { + out = g_policiesMetadata[policy].code[2]; + } else if (hasEquipped && hasOutfit) { + out = g_policiesMetadata[policy].code[3]; + } + switch (out) { + case 'E': + return Selection::EQUIPPED; + case 'O': + return Selection::OUTFIT; + default: + return Selection::EMPTY; + } } } diff --git a/src/OutfitSystem.cpp b/src/OutfitSystem.cpp index 58829f3..a8c4eff 100644 --- a/src/OutfitSystem.cpp +++ b/src/OutfitSystem.cpp @@ -372,7 +372,7 @@ namespace OutfitSystem { std::vector result; auto& service = ArmorAddonOverrideService::GetInstance(); auto& outfit = service.getOutfit(name.data()); - for (auto slot = RE::BIPED_OBJECTS_META::firstSlot; slot < RE::BIPED_OBJECTS_META::numSlots; slot++) { + for (auto slot = RE::BIPED_OBJECTS_META::kFirstSlot; slot < RE::BIPED_OBJECTS_META::kNumSlots; slot++) { auto slotSpecificPolicy = outfit.slotPolicies.find(static_cast(slot)); if (slotSpecificPolicy != outfit.slotPolicies.end()) { result.emplace_back(SlotPolicy::g_policiesMetadata.at(static_cast(slotSpecificPolicy->second)).translationKey()); @@ -393,7 +393,7 @@ namespace OutfitSystem { LogExit exitPrint("BodySlotPolicy.SetBodySlotPoliciesForOutfit"sv); auto& service = ArmorAddonOverrideService::GetInstance(); auto& outfit = service.getOutfit(name.data()); - if (slot >= RE::BIPED_OBJECTS_META::numSlots) { + if (slot >= RE::BIPED_OBJECTS_META::kNumSlots) { LOG(err, "Invalid slot {}.", static_cast(slot)); return; } @@ -421,7 +421,7 @@ namespace OutfitSystem { return first.code == codeString; }); if (found == SlotPolicy::g_policiesMetadata.end()) return; - outfit.setAllSlotPolicy(static_cast(found - SlotPolicy::g_policiesMetadata.begin())); + outfit.setBlanketSlotPolicy(static_cast(found - SlotPolicy::g_policiesMetadata.begin())); } void SetBodySlotPolicyToDefaultForOutfit(RE::BSScript::IVirtualMachine* registry, std::uint32_t stackId,