Skip to content

Commit

Permalink
revert item equipping
Browse files Browse the repository at this point in the history
  • Loading branch information
powerof3 committed Mar 13, 2024
1 parent 7c06300 commit c94d422
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 92 deletions.
4 changes: 1 addition & 3 deletions SPID/include/Distribute.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,5 @@ namespace Distribute
}

void Distribute(NPCData& a_npcData, const PCLevelMult::Input& a_input);
void DistributeItems(NPCData& a_npcData, const PCLevelMult::Input& a_input);

void Distribute(NPCData& a_npcData, bool a_onlyLeveledEntries, bool a_noItems = false);
void Distribute(NPCData& a_npcData, bool a_onlyLeveledEntries);
}
2 changes: 1 addition & 1 deletion SPID/include/DistributeManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Distribute
{
inline RE::BGSKeyword* processed{ nullptr };
inline RE::BGSKeyword* processedOnLoad{ nullptr };
inline RE::BGSKeyword* processedOutfit{ nullptr };

namespace detail
{
Expand Down
63 changes: 8 additions & 55 deletions SPID/src/Distribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,9 @@ namespace Distribute
return false;
});

for_each_form<RE::TESObjectARMO>(a_npcData, Forms::skins, a_input, [&](auto* a_skin) {
if (npc->skin != a_skin) {
npc->skin = a_skin;
return true;
}
return false;
});

for_each_form<RE::BGSOutfit>(a_npcData, Forms::outfits, a_input, [&](auto* a_outfit) {
if (npc->defaultOutfit != a_outfit) {
if (npc->defaultOutfit != a_outfit && !npc->HasKeyword(processedOutfit)) {
npc->AddKeyword(processedOutfit);
npc->defaultOutfit = a_outfit;
return true;
}
Expand All @@ -129,63 +122,23 @@ namespace Distribute
}
return false;
});
}

void DistributeItems(NPCData& a_npcData, const PCLevelMult::Input& a_input)
{
if (a_input.onlyPlayerLevelEntries && PCLevelMult::Manager::GetSingleton()->HasHitLevelCap(a_input)) {
return;
}

const auto npc = a_npcData.GetNPC();
const auto actor = a_npcData.GetActor();

auto inv_before = actor->GetInventory([](auto& item) {
return item.Is(RE::FormType::Weapon, RE::FormType::Armor);
for_each_form<RE::TESBoundObject>(a_npcData, Forms::items, a_input, [&](std::map<RE::TESBoundObject*, IdxOrCount>& a_objects, const bool a_hasLvlItem) {
return npc->AddObjectsToContainer(a_objects, npc);
});

bool recalcInventory = false;
bool startsDead = actor->IsDead() || (actor->formFlags & RE::Actor::RecordFlags::kStartsDead) != 0;

for_each_form<RE::TESBoundObject>(a_npcData, Forms::items, a_input, [&](std::map<RE::TESBoundObject*, IdxOrCount>& a_objects, const bool a_hasLvlItem) {
if (npc->AddObjectsToContainer(a_objects, npc)) {
if (a_hasLvlItem) {
recalcInventory = true;
if (const auto invChanges = actor->GetInventoryChanges(true)) {
invChanges->InitLeveledItems();
}
} else if (!startsDead) {
for (auto& [item, count] : a_objects) {
if (item->Is(RE::FormType::Weapon, RE::FormType::Armor)) {
RE::ActorEquipManager::GetSingleton()->EquipObject(actor, item);
}
}
}
for_each_form<RE::TESObjectARMO>(a_npcData, Forms::skins, a_input, [&](auto* a_skin) {
if (npc->skin != a_skin) {
npc->skin = a_skin;
return true;
}
return false;
});

if (recalcInventory && !startsDead) {
auto inv_after = actor->GetInventory([](auto& item) {
return item.Is(RE::FormType::Weapon, RE::FormType::Armor);
});
for (auto& [item, data] : inv_after) {
auto& [count, extra] = data;
if (!inv_before.contains(item) && count > 0 && !extra->IsWorn()) {
RE::ActorEquipManager::GetSingleton()->EquipObject(actor, item);
}
}
}
}

void Distribute(NPCData& a_npcData, bool a_onlyLeveledEntries, bool a_noItems)
void Distribute(NPCData& a_npcData, bool a_onlyLeveledEntries)
{
const auto input = PCLevelMult::Input{ a_npcData.GetActor(), a_npcData.GetNPC(), a_onlyLeveledEntries };

Distribute(a_npcData, input);
if (!a_noItems) {
DistributeItems(a_npcData, input);
}
}
}
56 changes: 23 additions & 33 deletions SPID/src/DistributeManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ namespace Distribute
invChanges->InitOutfitItems(a_npc->defaultOutfit, a_npc->GetLevel());
}

std::vector<RE::TESObjectARMO*> armorToRemove;
std::vector<RE::TESObjectARMO*> armorToRemove;
std::vector<RE::TESBoundObject*> armorToEquip;

if (const auto invChanges = a_actor->GetInventoryChanges()) {
if (const auto entryLists = invChanges->entryList) {
Expand All @@ -65,38 +66,37 @@ namespace Distribute
continue;
}
}
RE::ActorEquipManager::GetSingleton()->EquipObject(a_actor, entryList->object, xList, 1, nullptr, true, true, false);
armorToEquip.push_back(entryList->object);
}
}
}
}
}
}

if (!armorToRemove.empty()) {
SKSE::GetTaskInterface()->AddTask([a_actor, armorToRemove]() {
for (auto& armor : armorToRemove) {
if (armor) {
a_actor->RemoveItem(armor, 1, RE::ITEM_REMOVE_REASON::kRemove, nullptr, nullptr);
}
SKSE::GetTaskInterface()->AddTask([a_actor, armorToRemove, armorToEquip]() {
for (auto& armor : armorToRemove) {
if (armor) {
a_actor->RemoveItem(armor, 1, RE::ITEM_REMOVE_REASON::kRemove, nullptr, nullptr);
}
});
}
}
for (auto& armor : armorToEquip) {
RE::ActorEquipManager::GetSingleton()->EquipObject(a_actor, armor, nullptr, 1, nullptr, true, true, false, false);
}
});
}

void detail::distribute_on_load(RE::Actor* a_actor, RE::TESNPC* a_npc)
{
const auto process = should_process_NPC(a_npc);
const auto processOnLoad = detail::should_process_NPC(a_npc, processedOnLoad);
if (process || processOnLoad) {
auto slots = detail::get_equipped_item_slots(a_actor);
a_actor->RemoveOutfitItems(nullptr);

if (should_process_NPC(a_npc)) {
auto npcData = NPCData(a_actor, a_npc);
if (process) {
Distribute(npcData, false, true);
}
if (processOnLoad) {
DistributeItems(npcData, { a_actor, a_npc, false });
}
Distribute(npcData, false);
}

detail::force_equip_outfit(a_actor, a_npc, slots);
}

namespace Actor
Expand All @@ -107,12 +107,7 @@ namespace Distribute
static bool thunk(RE::Character* a_this)
{
if (const auto npc = a_this->GetActorBase()) {
auto slots = detail::get_equipped_item_slots(a_this);
a_this->RemoveOutfitItems(nullptr);

detail::distribute_on_load(a_this, npc);

detail::force_equip_outfit(a_this, npc, slots);
}

return func(a_this);
Expand All @@ -131,15 +126,10 @@ namespace Distribute
func(a_this, a_buf);

if (const auto npc = a_this->GetActorBase()) {
auto slots = detail::get_equipped_item_slots(a_this);
a_this->RemoveOutfitItems(nullptr);

// some leveled npcs are completely reset upon loading
if (a_this->Is3DLoaded()) {
detail::distribute_on_load(a_this, npc);
}

detail::force_equip_outfit(a_this, npc, slots);
}
}
static inline REL::Relocation<decltype(thunk)> func;
Expand All @@ -164,8 +154,8 @@ namespace Distribute
if (processed = factory->Create(); processed) {
processed->formEditorID = "SPID_Processed";
}
if (processedOnLoad = factory->Create(); processedOnLoad) {
processedOnLoad->formEditorID = "SPID_ProcessedOnLoad";
if (processedOutfit = factory->Create(); processedOutfit) {
processedOutfit->formEditorID = "SPID_ProcessedOutfit";
}
}

Expand Down Expand Up @@ -195,7 +185,7 @@ namespace Distribute
if (const auto& actor = actorHandle.get()) {
if (const auto npc = actor->GetActorBase(); npc && detail::should_process_NPC(npc)) {
auto npcData = NPCData(actor.get(), npc);
Distribute(npcData, false, true);
Distribute(npcData, false);
++actorCount;
}
}
Expand All @@ -215,7 +205,7 @@ namespace Distribute
logger::info("{:*^50}", "RESULTS");

ForEachDistributable([&]<typename Form>(Distributables<Form>& a_distributable) {
if (a_distributable && a_distributable.GetType() != RECORD::kItem && a_distributable.GetType() != RECORD::kOutfit && a_distributable.GetType() != RECORD::kDeathItem) {
if (a_distributable && a_distributable.GetType() != RECORD::kDeathItem) {
logger::info("{}", RECORD::add[a_distributable.GetType()]);

auto& forms = a_distributable.GetForms();
Expand Down

0 comments on commit c94d422

Please sign in to comment.