Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added tweaks NWNX_TWEAKS_FIRE_EQUIP_EVENTS_FOR_ALL_CREATURES and NWNX_TWEAKS_DONT_DELAY_EQUIP_EVENT #1684

Merged
merged 4 commits into from
Sep 23, 2023
Merged
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ https://github.com/nwnxee/unified/compare/build8193.35.40...HEAD
- Events: added `NWNX_ON_CREATURE_JUMP_TO_POSITION_{BEFORE|AFTER}` which fires when a creature is being jumped to a new location (area + x/y/z coordinates).
- Events: added `NWNX_ON_CREATURE_JUMP_TO_OBJECT_{BEFORE|AFTER}` which fires when a creature is being jumped to a new location (to an object).
- Events: added skippable events `NWNX_ON_ITEMPROPERTY_EFFECT_(APPLIED|REMOVED)_*` which fire when the game applies or removes the effects from an itemproperty.

- Tweaks: added `NWNX_TWEAKS_FIRE_EQUIP_EVENTS_FOR_ALL_CREATURES` which makes the module OnPlayerEquipItem and OnPlayerUnEquipItem events fire for all creatures.
- Tweaks: added `NWNX_TWEAKS_DONT_DELAY_EQUIP_EVENT` which fixes Unequip/Equip events being out of sync if an item is equipped/unequipped multiple times per server tick.

##### New Plugins
- Resources: Adds `RESOURCES_*` variables for adding NWSync as a resource source, and specifying a replacement hak list.
Expand Down
3 changes: 2 additions & 1 deletion Plugins/Tweaks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ add_plugin(Tweaks
"RangedWeaponsUseOnHitCastSpellItemProperties.cpp"
"CastAllOnHitCastSpellItemProperties.cpp"
"FixAutoMapCrash.cpp"
"SetAreaCallsSetPosition.cpp")
"SetAreaCallsSetPosition.cpp"
"EquipUnequipEventTweaks.cpp")
105 changes: 105 additions & 0 deletions Plugins/Tweaks/EquipUnequipEventTweaks.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "nwnx.hpp"

#include "API/CNWSCreature.hpp"
#include "API/CNWSCreatureStats.hpp"
#include "API/CNWSItem.hpp"
#include "API/CNWSModule.hpp"
#include "API/CNWSInventory.hpp"
#include "API/CAppManager.hpp"
#include "API/CServerExoApp.hpp"
#include "API/CScriptEvent.hpp"
#include "API/CServerAIMaster.hpp"

namespace Tweaks {

using namespace NWNXLib;
using namespace NWNXLib::API;

static bool s_bEquipForAll;
static bool s_bNoEquipEventDelay;

void EquipUnequipEventTweaks() __attribute__((constructor));
void EquipUnequipEventTweaks()
{
s_bEquipForAll = Config::Get<bool>("FIRE_EQUIP_EVENTS_FOR_ALL_CREATURES", false);
s_bNoEquipEventDelay = Config::Get<bool>("DONT_DELAY_EQUIP_EVENT", false);

if (s_bEquipForAll)
LOG_INFO("OnPlayerEquipItem and OnPlayerUnEquipItem will fire for all creatures");
if (s_bNoEquipEventDelay)
LOG_INFO("OnPlayerEquipItem will fire without delay");

if (s_bEquipForAll || s_bNoEquipEventDelay)
{
static Hooks::Hook s_EquipItemHook = Hooks::HookFunction(&CNWSCreature::EquipItem,
+[](CNWSCreature* pCreature, uint32_t nInventorySlot, CNWSItem* pItem, BOOL bApplyPropertyEffects, BOOL bLoadingItem) -> BOOL
{
if (((s_bEquipForAll) || (pCreature->m_pStats->m_bIsPC)) && (!s_bNoEquipEventDelay))
{
CScriptEvent* pEvent = new CScriptEvent();
pEvent->m_nType = Constants::ScriptEvent::OnEquipItem;
pEvent->SetObjectID(0, pItem->m_idSelf);
pEvent->SetObjectID(1, pCreature->m_idSelf);
pEvent->SetInteger(0, pCreature->m_pInventory->GetArraySlotFromSlotFlag(nInventorySlot));

auto pServerAIMaster = Globals::AppManager()->m_pServerExoApp->GetServerAIMaster();
pServerAIMaster->AddEventDeltaTime(0, 0, pCreature->m_idSelf, Utils::GetModule()->m_idSelf, Constants::AIMasterEvent::SignalEvent, (void*)pEvent);
}

if (pCreature->m_idSelf != pItem->m_oidPossessor)
pItem->SetPossessor(pCreature->m_idSelf, false, false, false);

if (pCreature->m_pInventory->GetItemInInventory(pItem))
pCreature->UnequipItem(pItem, false);

if (bApplyPropertyEffects)
pItem->ApplyItemProperties(pCreature, nInventorySlot, bLoadingItem);

pCreature->m_pInventory->PutItemInSlot(nInventorySlot, pItem);
pCreature->ComputeArmourClass(pItem, true, false);
pCreature->m_pStats->UpdateCombatInformation();
pCreature->m_nEquippedWeight += pItem->GetWeight();

if (((s_bEquipForAll) || (pCreature->m_pStats->m_bIsPC)) && (s_bNoEquipEventDelay))
{
auto* pModule = Utils::GetModule();
pModule->m_oidLastItemEquippedBy = pCreature->m_idSelf;
pModule->m_oidLastItemEquipped = pItem->m_idSelf;
pModule->m_nLastItemEquippedSlot = pCreature->m_pInventory->GetArraySlotFromSlotFlag(nInventorySlot);
pModule->RunEventScript(15, nullptr);
}

return true;
}, Hooks::Order::Final);
}

if (s_bEquipForAll)
{
static Hooks::Hook s_UnEquipItemHook = Hooks::HookFunction(&CNWSCreature::UnequipItem,
+[](CNWSCreature* pCreature, CNWSItem * pItem, BOOL bUnequipWhilePolymorphed) -> BOOL
{
if ((pCreature->m_bIsPolymorphed) && (!bUnequipWhilePolymorphed))
return false;

if ((s_bEquipForAll) || (pCreature->m_pStats->m_bIsPC))
{
auto* pModule = Utils::GetModule();
pModule->m_oidLastItemUnequippedBy = pCreature->m_idSelf;
pModule->m_oidLastItemUnequipped = pItem->m_idSelf;
pModule->m_nLastItemUnequippedSlot = pCreature->m_pInventory->GetArraySlotFromSlotFlag(pCreature->m_pInventory->GetSlotFromItem(pItem));
pModule->RunEventScript(16, nullptr);
}

pItem->RemoveItemProperties(pCreature, pCreature->m_pInventory->GetSlotFromItem(pItem));
pCreature->m_pInventory->RemoveItem(pItem);
pCreature->ComputeArmourClass(pItem, true, false);

pCreature->m_nEquippedWeight -= pItem->GetWeight();
pCreature->m_bUpdateCombatInformation = true;

return true;
}, Hooks::Order::Final);
}
}

}
2 changes: 2 additions & 0 deletions Plugins/Tweaks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ Tweaks stuff. See below.
| `NWNX_TWEAKS_CAST_ALL_ON_HIT_CAST_SPELL_ITEM_PROPERTIES` | true or false | Casts all On Hit: Cast Spell item properties on hit, instead of only the first property. |
| `NWNX_TWEAKS_FIX_AUTOMAP_CRASH` | true or false | Fixes a server crash that happens when automap data is outdated for a player. |
| `NWNX_TWEAKS_SETAREA_CALLS_SETPOSITION` | true or false | If enabled, a creature getting added to an area will fire the `NWNX_ON_MATERIALCHANGE_*` and `NWNX_ON_CREATURE_TILE_CHANGE_*` events. |
| `NWNX_TWEAKS_FIRE_EQUIP_EVENTS_FOR_ALL_CREATURES` | true or false | The module OnPlayerEquipItem and OnPlayerUnEquipItem events are fired for all creatures |
| `NWNX_TWEAKS_DONT_DELAY_EQUIP_EVENT` | true or false | Fixes Unequip/Equip events being out of sync if an item is equipped/unequipped multiple times per server tick |

## Environment variable values

Expand Down