Skip to content

Commit 6af429b

Browse files
committed
Cache faction NPCs to mitigate performance issues
1 parent 60880ee commit 6af429b

File tree

3 files changed

+24
-20
lines changed

3 files changed

+24
-20
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required(VERSION 3.20)
22
set(NAME "po3_Tweaks" CACHE STRING "")
3-
set(VERSION 1.12.0 CACHE STRING "")
3+
set(VERSION 1.12.1 CACHE STRING "")
44
set(AE_VERSION 1)
55
set(VR_VERSION 1)
66

src/Tweaks/FactionStealing.cpp

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
11
#include "Tweaks.h"
2+
#include "Cache.h"
23

34
//removes steal tag if all faction members have appropriate relationship rank
45
namespace Tweaks::FactionStealing
56
{
67
struct detail
78
{
8-
static std::int32_t GetFavorCost(RE::TESNPC* a_player, RE::TESNPC* a_owner)
9+
static std::int32_t GetRelationshipFavorPointsValue(RE::TESNPC* a_player, RE::TESNPC* a_owner)
910
{
10-
using func_t = decltype(&GetFavorCost);
11+
using func_t = decltype(&GetRelationshipFavorPointsValue);
1112
static REL::Relocation<func_t> func{ REL_ID(23626, 24078) };
1213
return func(a_player, a_owner);
1314
}
1415

1516
static bool CanTake(RE::TESNPC* a_playerBase, RE::TESNPC* a_npc, std::int32_t a_cost)
1617
{
17-
const auto favorCost = GetFavorCost(a_playerBase, a_npc);
18-
return favorCost > 1 ?
19-
a_cost <= favorCost :
18+
const auto favorPoints = GetRelationshipFavorPointsValue(a_playerBase, a_npc);
19+
return favorPoints > 1 ?
20+
a_cost <= favorPoints :
2021
false;
2122
}
2223
};
2324

24-
struct CanTake
25+
struct IsFriendAnOwner
2526
{
2627
static bool func(const RE::PlayerCharacter* a_player, RE::TESForm* a_owner, std::int32_t a_cost)
2728
{
@@ -43,21 +44,24 @@ namespace Tweaks::FactionStealing
4344
return true;
4445
}
4546

46-
std::vector<RE::TESNPC*> factionNPCs{};
47-
48-
for (auto& npc : RE::TESDataHandler::GetSingleton()->GetFormArray<RE::TESNPC>()) {
49-
if (npc && !npc->IsDeleted()) {
50-
if (npc->IsInFaction(faction)) {
51-
factionNPCs.push_back(npc);
52-
} else if (auto actor = npc->GetUniqueActor(); actor && actor->IsInFaction(faction)) {
53-
factionNPCs.push_back(npc);
47+
static Map<RE::TESFaction*, std::vector<RE::TESNPC*>> factionNPCMap{};
48+
if (factionNPCMap.empty()) {
49+
for (auto& npc : RE::TESDataHandler::GetSingleton()->GetFormArray<RE::TESNPC>()) {
50+
if (npc && !npc->IsDeleted()) {
51+
for (auto& factionRank : npc->factions) {
52+
if (factionRank.faction) {
53+
factionNPCMap[factionRank.faction].push_back(npc);
54+
}
55+
}
5456
}
5557
}
5658
}
5759

58-
return std::ranges::all_of(factionNPCs, [&](const auto& npc) {
59-
return detail::CanTake(playerBase, npc, a_cost);
60-
});
60+
if (auto it = factionNPCMap.find(faction); it != factionNPCMap.end()) {
61+
return std::ranges::all_of(it->second, [&](const auto& npc) {
62+
return detail::CanTake(playerBase, npc, a_cost);
63+
});
64+
}
6165
}
6266

6367
return false;
@@ -73,7 +77,7 @@ namespace Tweaks::FactionStealing
7377
void Install()
7478
{
7579
REL::Relocation<std::uintptr_t> func{ REL_ID(39584, 40670) };
76-
stl::asm_replace<CanTake>(func.address());
80+
stl::asm_replace<IsFriendAnOwner>(func.address());
7781

7882
logger::info("\t\tInstalled faction stealing tweak"sv);
7983
}

vcpkg.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "po3tweaks",
3-
"version-string": "1.12.0",
3+
"version-string": "1.12.1",
44
"description": "Collection of bug fixes and tweaks for Skyrim SE/AE/VR",
55
"homepage": "https://github.com/powerof3/po3-Tweaks/",
66
"license": "MIT",

0 commit comments

Comments
 (0)