From 887d0703f75891fe41acd483a256cc2e6c81e0e9 Mon Sep 17 00:00:00 2001 From: Arkadii Hlushchevskyi Date: Sat, 17 Feb 2024 23:22:42 +0200 Subject: [PATCH 1/3] Added extra check for empty name. This is the case when NPC is marked as unique and is not supposed to get any generated name. --- src/NPCNameProvider.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/NPCNameProvider.cpp b/src/NPCNameProvider.cpp index 95f24e0..3822d3e 100644 --- a/src/NPCNameProvider.cpp +++ b/src/NPCNameProvider.cpp @@ -4,7 +4,9 @@ const char* NPCNameProvider::GetName(RE::Actor* actor) const { if (NND) { - return NND->GetName(actor, NND_API::NameContext::kEnemyHUD).data(); + if (auto name = NND->GetName(actor, NND_API::NameContext::kEnemyHUD); !name.empty()) { + return name.data(); + } } return actor->GetDisplayFullName(); From 39f97ef2b1b819815bb8c633031afb68e13fb639 Mon Sep 17 00:00:00 2001 From: Arkadii Hlushchevskyi Date: Sat, 17 Feb 2024 23:36:13 +0200 Subject: [PATCH 2/3] Added documentation for NND API. --- src/NND_API.h | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/NND_API.h b/src/NND_API.h index 0aef324..99c0167 100644 --- a/src/NND_API.h +++ b/src/NND_API.h @@ -35,10 +35,38 @@ namespace NND_API class IVNND1 { public: - virtual std::string_view GetName(RE::ActorHandle, NameContext) noexcept = 0; - virtual std::string_view GetName(const RE::Actor*, NameContext) noexcept = 0; - virtual void RevealName(RE::ActorHandle) noexcept = 0; - virtual void RevealName(RE::Actor*) noexcept = 0; + + /// + /// Retrieves a generated name for given actor appropriate in specified context. + /// Note that NND might not have a name for the actor. In this case an empty string will be returned. + /// + /// Actor for which the name should be retrieved. + /// Context in which the name needs to be displayed. Depending on context name might either shortened or formatted differently. + /// A name generated for the actor. If actor does not support generated names an empty string will be returned instead. + virtual std::string_view GetName(RE::ActorHandle actor, NameContext context) noexcept = 0; + + /// + /// Retrieves a generated name for given actor appropriate in specified context. + /// Note that NND might not have a name for the actor. In this case an empty string will be returned. + /// + /// Actor for which the name should be retrieved. + /// Context in which the name needs to be displayed. Depending on context name might either shortened or formatted differently. + /// A name generated for the actor. If actor does not support generated names an empty string will be returned instead. + virtual std::string_view GetName(const RE::Actor* actor, NameContext context) noexcept = 0; + + /// + /// Reveals a real name of the given actor to the player. If player already knows actor's name this method does nothing. + /// This method can be used to programatically introduce an actor to the player. + /// + /// Actor whose name should be revealed. + virtual void RevealName(RE::ActorHandle actor) noexcept = 0; + + /// + /// Reveals a real name of the given actor to the player. If player already knows actor's name this method does nothing. + /// This method can be used to programatically introduce an actor to the player. + /// + /// Actor whose name should be revealed. + virtual void RevealName(RE::Actor* actor) noexcept = 0; }; typedef void* (*_RequestPluginAPI)(const InterfaceVersion interfaceVersion); From d467e3062eef3d9c6b619448c2f1a8df689f6787 Mon Sep 17 00:00:00 2001 From: Arkadii Hlushchevskyi Date: Sat, 17 May 2025 00:06:02 +0300 Subject: [PATCH 3/3] Updated for V2 interface. I've patched the issue on NND side for V1. --- src/NND_API.h | 36 +++++++++++++++++++++++------------- src/NPCNameProvider.cpp | 2 +- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/NND_API.h b/src/NND_API.h index 99c0167..6f06fa7 100644 --- a/src/NND_API.h +++ b/src/NND_API.h @@ -11,7 +11,12 @@ namespace NND_API // Available NND interface versions enum class InterfaceVersion : uint8_t { - kV1 + kV1, + + /// + /// Introduces a new NameContext kDialogueHistory. Attempting to access it in older versions would return name for kOther context instead. + /// + kV2 }; enum class NameContext : uint8_t @@ -28,17 +33,19 @@ namespace NND_API kEnemyHUD, - kOther + kOther, + + kDialogueHistory }; // NND's modder interface class IVNND1 { public: - /// /// Retrieves a generated name for given actor appropriate in specified context. /// Note that NND might not have a name for the actor. In this case an empty string will be returned. + /// For backward compatibility reasons, V1 version will return actor->GetName() for kEnemyHUD context. /// /// Actor for which the name should be retrieved. /// Context in which the name needs to be displayed. Depending on context name might either shortened or formatted differently. @@ -48,27 +55,30 @@ namespace NND_API /// /// Retrieves a generated name for given actor appropriate in specified context. /// Note that NND might not have a name for the actor. In this case an empty string will be returned. + /// For backward compatibility reasons, V1 version will return actor->GetName() for kEnemyHUD context. /// /// Actor for which the name should be retrieved. /// Context in which the name needs to be displayed. Depending on context name might either shortened or formatted differently. /// A name generated for the actor. If actor does not support generated names an empty string will be returned instead. - virtual std::string_view GetName(const RE::Actor* actor, NameContext context) noexcept = 0; + virtual std::string_view GetName(RE::Actor* actor, NameContext context) noexcept = 0; /// - /// Reveals a real name of the given actor to the player. If player already knows actor's name this method does nothing. - /// This method can be used to programatically introduce an actor to the player. + /// Reveals a real name of the given actor to the player. If player already know actor's name this method does nothing. + /// This method can be used to programatically introduce the actor to the player. /// - /// Actor whose name should be revealed. + /// Actor whos name should be revealed. virtual void RevealName(RE::ActorHandle actor) noexcept = 0; - + /// - /// Reveals a real name of the given actor to the player. If player already knows actor's name this method does nothing. - /// This method can be used to programatically introduce an actor to the player. + /// Reveals a real name of the given actor to the player. If player already know actor's name this method does nothing. + /// This method can be used to programatically introduce the actor to the player. /// - /// Actor whose name should be revealed. + /// Actor whos name should be revealed. virtual void RevealName(RE::Actor* actor) noexcept = 0; }; + using IVNND2 = IVNND1; + typedef void* (*_RequestPluginAPI)(const InterfaceVersion interfaceVersion); /// @@ -77,9 +87,9 @@ namespace NND_API /// /// The interface version to request /// The pointer to the API singleton, or nullptr if request failed - [[nodiscard]] inline void* RequestPluginAPI(const InterfaceVersion a_interfaceVersion = InterfaceVersion::kV1) + [[nodiscard]] inline void* RequestPluginAPI(const InterfaceVersion a_interfaceVersion = InterfaceVersion::kV2) { - const auto pluginHandle = GetModuleHandle("NPCsNamesDistributor.dll"); + const auto pluginHandle = GetModuleHandle(reinterpret_cast("NPCsNamesDistributor.dll")); if (const _RequestPluginAPI requestAPIFunction = reinterpret_cast<_RequestPluginAPI>(GetProcAddress(pluginHandle, "RequestPluginAPI"))) { return requestAPIFunction(a_interfaceVersion); } diff --git a/src/NPCNameProvider.cpp b/src/NPCNameProvider.cpp index 3822d3e..38edb72 100644 --- a/src/NPCNameProvider.cpp +++ b/src/NPCNameProvider.cpp @@ -15,7 +15,7 @@ const char* NPCNameProvider::GetName(RE::Actor* actor) const void NPCNameProvider::RequestAPI() { if (!NND) { - NND = static_cast(NND_API::RequestPluginAPI(NND_API::InterfaceVersion::kV1)); + NND = static_cast(NND_API::RequestPluginAPI(NND_API::InterfaceVersion::kV2)); if (NND) { logger::info("Obtained NND API - {0:x}", reinterpret_cast(NND)); } else {