@@ -14,7 +14,7 @@ namespace PapyrusObjectREFR
1414 }
1515
1616 if (const auto TES = RE::TES::GetSingleton (); TES) {
17- const auto formType = static_cast < RE::FormType>(RE::FormType:: NPC) ;
17+ const auto formType = RE::FormType:: NPC;
1818
1919 TES->ForEachReferenceInRange (a_origin, a_radius, [&](RE::TESObjectREFR& a_ref) {
2020 auto base = a_ref.GetBaseObject ();
@@ -30,6 +30,30 @@ namespace PapyrusObjectREFR
3030 return vec;
3131 }
3232
33+ auto FindNearbyBooks (VM* a_vm, StackID a_stackID, RE::StaticFunctionTag*, RE::TESObjectREFR* a_origin, float a_radius) -> std::vector<RE::TESObjectREFR*>
34+ {
35+ std::vector<RE::TESObjectREFR*> vec;
36+
37+ if (!a_origin) {
38+ a_vm->TraceStack (" akOrigin cannot be None" , a_stackID, Severity::kInfo );
39+ return vec;
40+ }
41+
42+ if (const auto TES = RE::TES::GetSingleton (); TES) {
43+ const auto formType = RE::FormType::Book;
44+
45+ TES->ForEachReferenceInRange (a_origin, a_radius, [&](RE::TESObjectREFR& a_ref) {
46+ auto base = a_ref.GetBaseObject ();
47+ if (a_ref.As <RE::TESObjectREFR>() != a_origin && (a_ref.Is (formType) || base && base->Is (formType))) {
48+ vec.push_back (&a_ref);
49+ }
50+ return true ;
51+ });
52+ }
53+
54+ return vec;
55+ }
56+
3357 auto FindNearbyCommandedActors (VM* a_vm, StackID a_stackID, RE::StaticFunctionTag*, RE::TESObjectREFR* a_origin, float a_radius) -> std::vector<RE::Actor*>
3458 {
3559 std::vector<RE::Actor*> vec;
@@ -40,25 +64,25 @@ namespace PapyrusObjectREFR
4064 }
4165
4266 if (const auto TES = RE::TES::GetSingleton (); TES) {
43- const auto formType = static_cast < RE::FormType>(RE::FormType:: NPC) ;
67+ const auto formType = RE::FormType:: NPC;
4468
4569 TES->ForEachReferenceInRange (a_origin, a_radius, [&](RE::TESObjectREFR& a_ref) {
46- auto base = a_ref.GetBaseObject ();
47- if (a_ref.As <RE::TESObjectREFR>() != a_origin && (a_ref.Is (formType) || base && base->Is (formType))) {
48- if (auto actor = a_ref.As <RE::Actor>(); actor) {
49- if (actor->IsCommandedActor ()) {
50- if (const auto commandingActorHandle = actor->GetCommandingActor (); commandingActorHandle) {
51- const auto commandingActorPtr = commandingActorHandle.get ();
52- const auto commandingActor = commandingActorPtr.get ();
53-
54- if (commandingActor != nullptr && commandingActor == a_origin) {
55- vec.push_back (actor);
56- }
57- }
58- }
59- }
60- }
61- return true ;
70+ auto base = a_ref.GetBaseObject ();
71+ if (a_ref.As <RE::TESObjectREFR>() != a_origin && (a_ref.Is (formType) || base && base->Is (formType))) {
72+ if (auto actor = a_ref.As <RE::Actor>(); actor) {
73+ if (actor->IsCommandedActor ()) {
74+ if (const auto commandingActorHandle = actor->GetCommandingActor (); commandingActorHandle) {
75+ const auto commandingActorPtr = commandingActorHandle.get ();
76+ const auto commandingActor = commandingActorPtr.get ();
77+
78+ if (commandingActor != nullptr && commandingActor == a_origin) {
79+ vec.push_back (actor);
80+ }
81+ }
82+ }
83+ }
84+ }
85+ return true ;
6286 });
6387 }
6488
@@ -71,7 +95,7 @@ namespace PapyrusObjectREFR
7195
7296 if (const auto TES = RE::TES::GetSingleton (); TES) {
7397 if (const auto player = RE::PlayerCharacter::GetSingleton (); player) {
74- const auto formType = static_cast < RE::FormType>(RE::FormType:: NPC) ;
98+ const auto formType = RE::FormType:: NPC;
7599
76100 TES->ForEachReferenceInRange (player, a_radius, [&](RE::TESObjectREFR& a_ref) {
77101 auto base = a_ref.GetBaseObject ();
@@ -109,18 +133,18 @@ namespace PapyrusObjectREFR
109133 }
110134
111135 if (const auto TES = RE::TES::GetSingleton (); TES) {
112- const auto formType = static_cast < RE::FormType>(RE::FormType:: NPC) ;
136+ const auto formType = RE::FormType:: NPC;
113137
114138 TES->ForEachReferenceInRange (a_origin, a_radius, [&](RE::TESObjectREFR& a_ref) {
115- auto base = a_ref.GetBaseObject ();
116- if (a_ref.As <RE::TESObjectREFR>() != a_origin && (a_ref.Is (formType) || base && base->Is (formType))) {
117- if (auto actor = a_ref.As <RE::Actor>(); actor) {
118- if (actor->IsSummoned ()) {
119- vec.push_back (actor);
120- }
121- }
122- }
123- return true ;
139+ auto base = a_ref.GetBaseObject ();
140+ if (a_ref.As <RE::TESObjectREFR>() != a_origin && (a_ref.Is (formType) || base && base->Is (formType))) {
141+ if (auto actor = a_ref.As <RE::Actor>(); actor) {
142+ if (actor->IsSummoned ()) {
143+ vec.push_back (actor);
144+ }
145+ }
146+ }
147+ return true ;
124148 });
125149 }
126150
@@ -133,9 +157,8 @@ namespace PapyrusObjectREFR
133157
134158 if (const auto TES = RE::TES::GetSingleton (); TES) {
135159 if (const auto player = RE::PlayerCharacter::GetSingleton (); player) {
136-
137160 if (player->teammateCount > 0 ) {
138- const auto formType = static_cast < RE::FormType>(RE::FormType:: NPC) ;
161+ const auto formType = RE::FormType:: NPC;
139162
140163 TES->ForEachReferenceInRange (player, a_radius, [&](RE::TESObjectREFR& a_ref) {
141164 auto base = a_ref.GetBaseObject ();
@@ -155,6 +178,51 @@ namespace PapyrusObjectREFR
155178 return vec;
156179 }
157180
181+ auto TryAffixDisplayName (VM* a_vm, StackID a_stackID, RE::StaticFunctionTag*, RE::TESObjectREFR* a_ref, RE::BGSMessage* a_message, bool a_prepend, bool a_force) -> bool
182+ {
183+ if (!a_ref) {
184+ a_vm->TraceStack (" akRef cannot be None" , a_stackID, Severity::kInfo );
185+ return false ;
186+ }
187+
188+ if (!a_message) {
189+ a_vm->TraceStack (" akMessage cannot be None" , a_stackID, Severity::kInfo );
190+ return false ;
191+ }
192+
193+ const std::string_view displayName = a_ref->GetDisplayFullName ();
194+
195+ if (displayName.empty ()) {
196+ return false ;
197+ }
198+
199+ const std::string_view affix = a_message->GetFullName ();
200+
201+ if (affix.empty ()) {
202+ return false ;
203+ }
204+
205+ std::string_view fullName = displayName;
206+
207+ if (const auto base = a_ref->GetBaseObject (); base) {
208+ fullName = base->GetName ();
209+ }
210+
211+ if (a_prepend && !displayName.starts_with (affix)) {
212+ std::stringstream ss;
213+ ss << affix << ' ' << fullName;
214+ return a_ref->SetDisplayName (ss.str (), a_force);
215+ }
216+
217+ if (!a_prepend && !displayName.ends_with (affix)) {
218+ std::stringstream ss;
219+ ss << fullName << ' ' << affix;
220+ return a_ref->SetDisplayName (ss.str (), a_force);
221+ }
222+
223+ return false ;
224+ }
225+
158226 auto RegisterFuncs (VM* a_vm) -> bool
159227 {
160228 if (!a_vm) {
@@ -163,10 +231,12 @@ namespace PapyrusObjectREFR
163231 }
164232
165233 a_vm->RegisterFunction (" FindNearbyActors" , PROJECT_NAME, FindNearbyActors);
234+ a_vm->RegisterFunction (" FindNearbyBooks" , PROJECT_NAME, FindNearbyBooks);
166235 a_vm->RegisterFunction (" FindNearbyCommandedActors" , PROJECT_NAME, FindNearbyCommandedActors);
167236 a_vm->RegisterFunction (" FindNearbyFollowers" , PROJECT_NAME, FindNearbyFollowers);
168237 a_vm->RegisterFunction (" FindNearbySummons" , PROJECT_NAME, FindNearbySummons);
169238 a_vm->RegisterFunction (" FindNearbyTeammates" , PROJECT_NAME, FindNearbyTeammates);
239+ a_vm->RegisterFunction (" TryAffixDisplayName" , PROJECT_NAME, TryAffixDisplayName);
170240
171241 return true ;
172242 }
0 commit comments