From 55585b27a44abae40816389c42f3751feda05e5f Mon Sep 17 00:00:00 2001 From: plenarius Date: Thu, 26 Nov 2020 19:05:17 -0500 Subject: [PATCH 1/3] Experimental: Attempt to correct a crash involving faction/reputations --- CHANGELOG.md | 1 + Plugins/Experimental/CMakeLists.txt | 1 + Plugins/Experimental/Experimental.cpp | 7 +++ Plugins/Experimental/Experimental.hpp | 2 + .../Experimentals/AdjustReputationFix.cpp | 52 +++++++++++++++++++ .../Experimentals/AdjustReputationFix.hpp | 16 ++++++ Plugins/Experimental/README.md | 1 + 7 files changed, 80 insertions(+) create mode 100644 Plugins/Experimental/Experimentals/AdjustReputationFix.cpp create mode 100644 Plugins/Experimental/Experimentals/AdjustReputationFix.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 9691616de8..70aad32838 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ https://github.com/nwnxee/unified/compare/build8193.16...HEAD - Events: added Combat Enter/Exit events to CombatEvents - Events: Stealth Mode can now bypass or perform Hide in Plain Sight with return values of "0" or "1" respectively - Events: Added Skippable/Result Changeable Faction Reputation event to FactionEvents +- Experimental: Added `NWNX_EXPERIMENTAL_ADJUST_REPUTATION_FIX` in an effort to correct a crash with factions/reputation - Tweaks: `NWNX_TWEAKS_HIDE_PLAYERS_ON_CHAR_LIST` - Tweaks: `NWNX_TWEAKS_FIX_ARMOR_DEX_BONUS_UNDER_ONE` - Tweaks: `NWNX_TWEAKS_FIX_ITEM_NULLPTR_IN_CITEMREPOSITORY` diff --git a/Plugins/Experimental/CMakeLists.txt b/Plugins/Experimental/CMakeLists.txt index eb72e3b4dd..cc2fd26bc9 100644 --- a/Plugins/Experimental/CMakeLists.txt +++ b/Plugins/Experimental/CMakeLists.txt @@ -1,4 +1,5 @@ add_plugin(Experimental "Experimental.cpp" "Experimentals/SuppressPlayerLoginInfo.cpp" + "Experimentals/AdjustReputationFix.cpp" ) diff --git a/Plugins/Experimental/Experimental.cpp b/Plugins/Experimental/Experimental.cpp index eecb70aa9b..a4d2bf84ed 100644 --- a/Plugins/Experimental/Experimental.cpp +++ b/Plugins/Experimental/Experimental.cpp @@ -1,5 +1,6 @@ #include "Experimental.hpp" #include "Experimentals/SuppressPlayerLoginInfo.hpp" +#include "Experimentals/AdjustReputationFix.hpp" #include "Services/Config/Config.hpp" @@ -24,6 +25,12 @@ Experimental::Experimental(Services::ProxyServiceList* services) LOG_INFO("EXPERIMENTAL: Suppressing playerlist and player login/logout messages for non DMs."); m_SuppressPlayerLoginInfo = std::make_unique(GetServices()->m_hooks.get()); } + + if (GetServices()->m_config->Get("ADJUST_REPUTATION_FIX", false)) + { + LOG_INFO("EXPERIMENTAL: Attempting to resolve faction/reputation crash."); + m_AdjustReputationFix = std::make_unique(GetServices()->m_hooks.get()); + } } Experimental::~Experimental() diff --git a/Plugins/Experimental/Experimental.hpp b/Plugins/Experimental/Experimental.hpp index 084f8e279a..d3ea435f01 100644 --- a/Plugins/Experimental/Experimental.hpp +++ b/Plugins/Experimental/Experimental.hpp @@ -5,6 +5,7 @@ namespace Experimental { class SuppressPlayerLoginInfo; +class AdjustReputationFix; class Experimental : public NWNXLib::Plugin { @@ -14,6 +15,7 @@ class Experimental : public NWNXLib::Plugin private: std::unique_ptr m_SuppressPlayerLoginInfo; + std::unique_ptr m_AdjustReputationFix; }; } diff --git a/Plugins/Experimental/Experimentals/AdjustReputationFix.cpp b/Plugins/Experimental/Experimentals/AdjustReputationFix.cpp new file mode 100644 index 0000000000..c817ca54a9 --- /dev/null +++ b/Plugins/Experimental/Experimentals/AdjustReputationFix.cpp @@ -0,0 +1,52 @@ +#include "Experimentals/AdjustReputationFix.hpp" + +#include "Services/Hooks/Hooks.hpp" + +#include "API/CAppManager.hpp" +#include "API/CFactionManager.hpp" +#include "API/CNWSCreature.hpp" +#include "API/CNWSCreatureStats.hpp" +#include "API/CServerExoApp.hpp" +#include "API/CServerExoAppInternal.hpp" +#include "API/Functions.hpp" +#include "API/Globals.hpp" + +namespace Experimental { + +using namespace NWNXLib; +using namespace NWNXLib::API; + +AdjustReputationFix::AdjustReputationFix(Services::HooksProxy* hooker) +{ + hooker->RequestExclusiveHook(&CNWSCreature__AdjustReputation_Hook); +} + +void AdjustReputationFix::CNWSCreature__AdjustReputation_Hook(CNWSCreature *pThis, int32_t nFactionId, int32_t nAdjustment) +{ + auto* pFactionManager = Globals::AppManager()->m_pServerExoApp->m_pcExoAppInternal->m_pFactionManager; + + if (!pFactionManager->GetIsNPCFaction(nFactionId)) + return; + + if (pThis->m_bPlayerCharacter || pThis->GetIsPossessedFamiliar()) + { + if (pThis->m_pReputation) + { + int32_t index = nFactionId - 1; + if (index >= 0 && index < pThis->m_pReputation->num) + { + pThis->m_pReputation->element[index] += nAdjustment; + pThis->m_pReputation->element[index] = std::clamp(pThis->m_pReputation->element[index], 0, 100); + } + } + } + else + { + if (pThis->m_pStats->m_nFactionId != nFactionId) + { + int32_t rep = pFactionManager->GetNPCFactionReputation(pThis->m_pStats->m_nFactionId, nFactionId); + pFactionManager->SetNPCFactionReputation(pThis->m_pStats->m_nFactionId, nFactionId, (rep + nAdjustment)); + } + } +} +} diff --git a/Plugins/Experimental/Experimentals/AdjustReputationFix.hpp b/Plugins/Experimental/Experimentals/AdjustReputationFix.hpp new file mode 100644 index 0000000000..63bde44342 --- /dev/null +++ b/Plugins/Experimental/Experimentals/AdjustReputationFix.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "Common.hpp" + +namespace Experimental { + +class AdjustReputationFix +{ +public: + AdjustReputationFix(NWNXLib::Services::HooksProxy* hooker); + +private: + static void CNWSCreature__AdjustReputation_Hook(CNWSCreature*, int32_t, int32_t); +}; + +} diff --git a/Plugins/Experimental/README.md b/Plugins/Experimental/README.md index cbb38225ea..47c2d2b68e 100644 --- a/Plugins/Experimental/README.md +++ b/Plugins/Experimental/README.md @@ -15,3 +15,4 @@ The following environmental variable is required to load the plugin: | Variable Name | Value | Notes | | ------------- | :----: | ------------------------------------ | | `NWNX_EXPERIMENTAL_SUPPRESS_PLAYER_LOGIN_INFO` | true/false | Suppresses the playerlist and player login/logout messages for all players except DMs. This functionality is not compatible with NWNX_Rename. | +| `NWNX_EXPERIMENTAL_ADJUST_REPUTATION_FIX` | true/false | Attempts to correct a crash involving faction/reputations. | From 2583701376a57042cb10effac81a925077340c88 Mon Sep 17 00:00:00 2001 From: Varenx Date: Fri, 27 Nov 2020 00:11:12 +0000 Subject: [PATCH 2/3] Set{Dawn,Dusk}Hour --- CHANGELOG.md | 2 ++ Plugins/Util/NWScript/nwnx_util.nss | 24 ++++++++++++++++++++++++ Plugins/Util/Util.cpp | 20 ++++++++++++++++++++ Plugins/Util/Util.hpp | 2 ++ 4 files changed, 48 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9691616de8..8bb9734e94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,8 @@ The following plugins were added: - Player: CloseStore() - Race: SetFavoredEnemyFeat() - Util: GetScriptParamIsSet() +- Util: SetDawnHour() +- Util: SetDuskHour() ### Changed - Area: ExportGIT() now supports valid custom resource directory aliases. diff --git a/Plugins/Util/NWScript/nwnx_util.nss b/Plugins/Util/NWScript/nwnx_util.nss index 0b5d457d8a..42412d04f2 100644 --- a/Plugins/Util/NWScript/nwnx_util.nss +++ b/Plugins/Util/NWScript/nwnx_util.nss @@ -223,6 +223,14 @@ string NWNX_Util_GetResourceOverride(int nResType, string sName); /// @return TRUE if the script param is set, FALSE if not or on error. int NWNX_Util_GetScriptParamIsSet(string sParamName); +/// @brief Set the module dawn hour. +/// @param nDawnHour The new dawn hour +void NWNX_Util_SetDawnHour(int nDawnHour); + +/// @brief Set the module dusk hour. +/// @param nDuskHour The new dusk hour +void NWNX_Util_SetDuskHour(int nDuskHour); + /// @} string NWNX_Util_GetCurrentScriptName(int depth = 0) @@ -540,3 +548,19 @@ int NWNX_Util_GetScriptParamIsSet(string sParamName) return NWNX_GetReturnValueInt(NWNX_Util, sFunc); } + +void NWNX_Util_SetDawnHour(int nDawnHour) +{ + string sFunc = "SetDawnHour"; + + NWNX_PushArgumentInt(NWNX_Util, sFunc, nDawnHour); + NWNX_CallFunction(NWNX_Util, sFunc); +} + +void NWNX_Util_SetDuskHour(int nDuskHour) +{ + string sFunc = "SetDuskHour"; + + NWNX_PushArgumentInt(NWNX_Util, sFunc, nDuskHour); + NWNX_CallFunction(NWNX_Util, sFunc); +} \ No newline at end of file diff --git a/Plugins/Util/Util.cpp b/Plugins/Util/Util.cpp index 67f2466cda..fd82239cdb 100644 --- a/Plugins/Util/Util.cpp +++ b/Plugins/Util/Util.cpp @@ -91,6 +91,8 @@ Util::Util(Services::ProxyServiceList* services) REGISTER(SetResourceOverride); REGISTER(GetResourceOverride); REGISTER(GetScriptParamIsSet); + REGISTER(SetDawnHour); + REGISTER(SetDuskHour); #undef REGISTER @@ -799,4 +801,22 @@ ArgumentStack Util::GetScriptParamIsSet(ArgumentStack&& args) return Services::Events::Arguments(retVal); } +ArgumentStack Util::SetDawnHour(ArgumentStack &&args) +{ + const auto dawnHour = Services::Events::ExtractArgument(args); + ASSERT_OR_THROW(dawnHour > 0); + ASSERT_OR_THROW(dawnHour <= 255); + Utils::GetModule()->m_nDawnHour = dawnHour; + return Services::Events::Arguments(); +} + +ArgumentStack Util::SetDuskHour(ArgumentStack &&args) +{ + const auto duskHour = Services::Events::ExtractArgument(args); + ASSERT_OR_THROW(duskHour > 0); + ASSERT_OR_THROW(duskHour <= 255); + Utils::GetModule()->m_nDuskHour = duskHour; + return Services::Events::Arguments(); +} + } diff --git a/Plugins/Util/Util.hpp b/Plugins/Util/Util.hpp index 07f15cdd11..c4abe47d39 100644 --- a/Plugins/Util/Util.hpp +++ b/Plugins/Util/Util.hpp @@ -47,6 +47,8 @@ class Util : public NWNXLib::Plugin ArgumentStack SetResourceOverride (ArgumentStack&& args); ArgumentStack GetResourceOverride (ArgumentStack&& args); ArgumentStack GetScriptParamIsSet (ArgumentStack&& args); + ArgumentStack SetDawnHour (ArgumentStack&& args); + ArgumentStack SetDuskHour (ArgumentStack&& args); size_t m_resRefIndex; std::vector m_listResRefs; From 0aba89aa70de0bcf305da33aa07c0634c8e1d783 Mon Sep 17 00:00:00 2001 From: Varenx Date: Fri, 27 Nov 2020 01:53:23 +0000 Subject: [PATCH 3/3] Fixed assers to only allow valid hours (0<=nHour<=23) --- Plugins/Util/Util.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Plugins/Util/Util.cpp b/Plugins/Util/Util.cpp index fd82239cdb..7873f6c52f 100644 --- a/Plugins/Util/Util.cpp +++ b/Plugins/Util/Util.cpp @@ -804,8 +804,8 @@ ArgumentStack Util::GetScriptParamIsSet(ArgumentStack&& args) ArgumentStack Util::SetDawnHour(ArgumentStack &&args) { const auto dawnHour = Services::Events::ExtractArgument(args); - ASSERT_OR_THROW(dawnHour > 0); - ASSERT_OR_THROW(dawnHour <= 255); + ASSERT_OR_THROW(dawnHour >= 0); + ASSERT_OR_THROW(dawnHour <= 23); Utils::GetModule()->m_nDawnHour = dawnHour; return Services::Events::Arguments(); } @@ -813,8 +813,8 @@ ArgumentStack Util::SetDawnHour(ArgumentStack &&args) ArgumentStack Util::SetDuskHour(ArgumentStack &&args) { const auto duskHour = Services::Events::ExtractArgument(args); - ASSERT_OR_THROW(duskHour > 0); - ASSERT_OR_THROW(duskHour <= 255); + ASSERT_OR_THROW(duskHour >= 0); + ASSERT_OR_THROW(duskHour <= 23); Utils::GetModule()->m_nDuskHour = duskHour; return Services::Events::Arguments(); }