From 1110e42b206e34beccc6c57e4d9cf0bea360a3b3 Mon Sep 17 00:00:00 2001 From: Robbe Bryssinck Date: Mon, 27 Dec 2021 17:27:40 +0100 Subject: [PATCH] feat: Actor::SetFullContainer() --- Code/client/Games/ExtraData.h | 6 ++-- Code/client/Games/Skyrim/Actor.cpp | 38 ++++++++++++++++++++ Code/client/Games/Skyrim/Actor.h | 1 + Code/client/Games/Skyrim/TESObjectREFR.cpp | 7 +++- Code/client/Games/Skyrim/TESObjectREFR.h | 2 +- Code/client/Services/Generic/TestService.cpp | 3 +- 6 files changed, 51 insertions(+), 6 deletions(-) diff --git a/Code/client/Games/ExtraData.h b/Code/client/Games/ExtraData.h index 97cb0a5e2..154d636d7 100644 --- a/Code/client/Games/ExtraData.h +++ b/Code/client/Games/ExtraData.h @@ -44,7 +44,7 @@ struct BSExtraDataList #if TP_FALLOUT4 void* unk0; #endif - BSExtraData* data; + BSExtraData* data = nullptr; struct Bitfield { @@ -54,6 +54,6 @@ struct BSExtraDataList void* unk10; #endif - Bitfield* bitfield; - mutable BSRecursiveLock lock; + Bitfield* bitfield{}; + mutable BSRecursiveLock lock{}; }; diff --git a/Code/client/Games/Skyrim/Actor.cpp b/Code/client/Games/Skyrim/Actor.cpp index 79fd3552f..33350ab26 100644 --- a/Code/client/Games/Skyrim/Actor.cpp +++ b/Code/client/Games/Skyrim/Actor.cpp @@ -375,6 +375,44 @@ Container Actor::GetFullContainer() const noexcept return fullContainer; } +void Actor::SetFullContainer(Container& acContainer) noexcept +{ + RemoveAllItems(); + + std::sort(acContainer.Entries.begin(), acContainer.Entries.end(), [](Container::Entry lhs, Container::Entry rhs) { + return lhs.Count < rhs.Count; + }); + + Container currentContainer = GetFullContainer(); + for (auto currentEntry : currentContainer.Entries) + { + auto& duplicate = std::find_if(acContainer.Entries.begin(), acContainer.Entries.end(), [currentEntry](Container::Entry newEntry) { + return newEntry.CanBeMerged(currentEntry); + }); + + if (duplicate != std::end(acContainer.Entries)) + { + duplicate->Count -= currentEntry.Count; + continue; + } + else + { + acContainer.Entries.push_back(*duplicate); + Container::Entry& back = acContainer.Entries.back(); + back.Count *= -1; + } + } + + std::remove_if(acContainer.Entries.begin(), acContainer.Entries.end(), [](Container::Entry entry) { + return entry.Count == 0; + }); + + for (const Container::Entry& entry : acContainer.Entries) + { + AddItem(entry); + } +} + Factions Actor::GetFactions() const noexcept { Factions result; diff --git a/Code/client/Games/Skyrim/Actor.h b/Code/client/Games/Skyrim/Actor.h index b1b7d1828..8f29ed934 100644 --- a/Code/client/Games/Skyrim/Actor.h +++ b/Code/client/Games/Skyrim/Actor.h @@ -208,6 +208,7 @@ struct Actor : TESObjectREFR void SetFactionRank(const TESFaction* apFaction, int8_t aRank) noexcept; void ForcePosition(const NiPoint3& acPosition) noexcept; void SetWeaponDrawnEx(bool aDraw) noexcept; + void SetFullContainer(Container& acContainer) noexcept; // Actions void UnEquipAll() noexcept; diff --git a/Code/client/Games/Skyrim/TESObjectREFR.cpp b/Code/client/Games/Skyrim/TESObjectREFR.cpp index 66236d523..0071e043c 100644 --- a/Code/client/Games/Skyrim/TESObjectREFR.cpp +++ b/Code/client/Games/Skyrim/TESObjectREFR.cpp @@ -149,7 +149,7 @@ int64_t TESObjectREFR::GetItemCountInInventory(TESForm* apItem) const noexcept return count; } -void TESObjectREFR::AddItem(Container::Entry& arEntry) noexcept +void TESObjectREFR::AddItem(const Container::Entry& arEntry) noexcept { ModSystem& modSystem = World::Get().GetModSystem(); @@ -166,6 +166,7 @@ void TESObjectREFR::AddItem(Container::Entry& arEntry) noexcept if (arEntry.ContainsExtraData()) { pExtraData = Memory::Allocate(); + pExtraData->data = nullptr; pExtraData->lock.m_counter = pExtraData->lock.m_tid = 0; pExtraData->bitfield = Memory::Allocate(); memset(pExtraData->bitfield, 0, 0x18); @@ -173,6 +174,7 @@ void TESObjectREFR::AddItem(Container::Entry& arEntry) noexcept if (arEntry.ExtraCharge > 0.f) { ExtraCharge* pExtraCharge = Memory::Allocate(); + *((uint64_t*)pExtraCharge) = 0x141623AB0; pExtraCharge->fCharge = arEntry.ExtraCharge; pExtraData->Add(ExtraData::Charge, pExtraCharge); } @@ -185,6 +187,7 @@ void TESObjectREFR::AddItem(Container::Entry& arEntry) noexcept if (arEntry.ExtraHealth > 0.f) { ExtraHealth* pExtraHealth = Memory::Allocate(); + *((uint64_t*)pExtraHealth) = 0x141623A50; pExtraHealth->fHealth = arEntry.ExtraHealth; pExtraData->Add(ExtraData::Health, pExtraHealth); } @@ -209,6 +212,7 @@ void TESObjectREFR::AddItem(Container::Entry& arEntry) noexcept if (arEntry.ExtraSoulLevel > 0 && arEntry.ExtraSoulLevel <= 5) { ExtraSoul* pExtraSoul = Memory::Allocate(); + *((uint64_t*)pExtraSoul) = 0x141627220; pExtraSoul->cSoul = static_cast(arEntry.ExtraSoulLevel); pExtraData->Add(ExtraData::Soul, pExtraSoul); } @@ -216,6 +220,7 @@ void TESObjectREFR::AddItem(Container::Entry& arEntry) noexcept if (!arEntry.ExtraTextDisplayName.empty()) { ExtraTextDisplayData* pExtraText = Memory::Allocate(); + *((uint64_t*)pExtraText) = 0x1416244D0; pExtraText->DisplayName = arEntry.ExtraTextDisplayName.c_str(); pExtraData->Add(ExtraData::TextDisplayData, pExtraText); } diff --git a/Code/client/Games/Skyrim/TESObjectREFR.h b/Code/client/Games/Skyrim/TESObjectREFR.h index d1649761e..2e1e67636 100644 --- a/Code/client/Games/Skyrim/TESObjectREFR.h +++ b/Code/client/Games/Skyrim/TESObjectREFR.h @@ -170,7 +170,7 @@ struct TESObjectREFR : TESForm Lock* CreateLock() noexcept; void LockChange() noexcept; - void AddItem(Container::Entry& arEntry) noexcept; + void AddItem(const Container::Entry& arEntry) noexcept; BSHandleRefObject handleRefObject; uintptr_t unk1C; diff --git a/Code/client/Services/Generic/TestService.cpp b/Code/client/Services/Generic/TestService.cpp index ea85cb9a9..fc7136bcf 100644 --- a/Code/client/Services/Generic/TestService.cpp +++ b/Code/client/Services/Generic/TestService.cpp @@ -73,6 +73,7 @@ void __declspec(noinline) TestService::PlaceActorInWorld() noexcept auto pActor = Actor::Create(pPlayerBaseForm); //pActor->SetInventory(PlayerCharacter::Get()->GetInventory()); + pActor->SetFullContainer(PlayerCharacter::Get()->GetFullContainer()); m_actors.emplace_back(pActor); } @@ -183,6 +184,7 @@ void TestService::OnUpdate(const UpdateEvent& acUpdateEvent) noexcept { s_f8Pressed = true; + /* auto fullContainer = PlayerCharacter::Get()->GetFullContainer(); spdlog::info("Full container entries: {}", fullContainer.Entries.size()); @@ -195,7 +197,6 @@ void TestService::OnUpdate(const UpdateEvent& acUpdateEvent) noexcept } } - /* auto* pActor = (Actor*)TESForm::GetById(0xFF000DA5); pActor->SetWeaponDrawnEx(true);