Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 46 additions & 8 deletions src/NND_API.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ namespace NND_API
// Available NND interface versions
enum class InterfaceVersion : uint8_t
{
kV1
kV1,

/// <summary>
/// Introduces a new NameContext kDialogueHistory. Attempting to access it in older versions would return name for kOther context instead.
/// </summary>
kV2
};

enum class NameContext : uint8_t
Expand All @@ -28,19 +33,52 @@ namespace NND_API

kEnemyHUD,

kOther
kOther,

kDialogueHistory
};

// NND's modder interface
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;
/// <summary>
/// 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.
/// </summary>
/// <param name="actor">Actor for which the name should be retrieved.</param>
/// <param name="context">Context in which the name needs to be displayed. Depending on context name might either shortened or formatted differently.</param>
/// <returns>A name generated for the actor. If actor does not support generated names an empty string will be returned instead.</returns>
virtual std::string_view GetName(RE::ActorHandle actor, NameContext context) noexcept = 0;

/// <summary>
/// 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.
/// </summary>
/// <param name="actor">Actor for which the name should be retrieved.</param>
/// <param name="context">Context in which the name needs to be displayed. Depending on context name might either shortened or formatted differently.</param>
/// <returns>A name generated for the actor. If actor does not support generated names an empty string will be returned instead.</returns>
virtual std::string_view GetName(RE::Actor* actor, NameContext context) noexcept = 0;

/// <summary>
/// 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.
/// </summary>
/// <param name="actor">Actor whos name should be revealed.</param>
virtual void RevealName(RE::ActorHandle actor) noexcept = 0;

/// <summary>
/// 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.
/// </summary>
/// <param name="actor">Actor whos name should be revealed.</param>
virtual void RevealName(RE::Actor* actor) noexcept = 0;
};

using IVNND2 = IVNND1;

typedef void* (*_RequestPluginAPI)(const InterfaceVersion interfaceVersion);

/// <summary>
Expand All @@ -49,9 +87,9 @@ namespace NND_API
/// </summary>
/// <param name="a_interfaceVersion">The interface version to request</param>
/// <returns>The pointer to the API singleton, or nullptr if request failed</returns>
[[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<LPCWSTR>("NPCsNamesDistributor.dll"));
if (const _RequestPluginAPI requestAPIFunction = reinterpret_cast<_RequestPluginAPI>(GetProcAddress(pluginHandle, "RequestPluginAPI"))) {
return requestAPIFunction(a_interfaceVersion);
}
Expand Down
6 changes: 4 additions & 2 deletions src/NPCNameProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -13,7 +15,7 @@ const char* NPCNameProvider::GetName(RE::Actor* actor) const
void NPCNameProvider::RequestAPI()
{
if (!NND) {
NND = static_cast<NND_API::IVNND1*>(NND_API::RequestPluginAPI(NND_API::InterfaceVersion::kV1));
NND = static_cast<NND_API::IVNND1*>(NND_API::RequestPluginAPI(NND_API::InterfaceVersion::kV2));
if (NND) {
logger::info("Obtained NND API - {0:x}", reinterpret_cast<uintptr_t>(NND));
} else {
Expand Down