From b1cf8300095d52a214f9d9ba382c14c2eac75af5 Mon Sep 17 00:00:00 2001 From: Elmsroth Date: Wed, 27 Mar 2024 01:28:37 +0100 Subject: [PATCH] chore(PlayerScript/Hook) : Add CanSetTradeItem Hook in PlayerScript (#18583) * chore(PlayerScript/Hook) : Add CanSetTradeItem Hook in PlayerScript * Allowing non traded slots * Fix typo and codestyle --- src/server/game/Handlers/TradeHandler.cpp | 9 +++++++++ .../game/Scripting/ScriptDefines/PlayerScript.cpp | 13 +++++++++++++ .../game/Scripting/ScriptDefines/PlayerScript.h | 10 ++++++++++ src/server/game/Scripting/ScriptMgr.h | 1 + 4 files changed, 33 insertions(+) diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp index 1608b1ae0..28ad91fdd 100644 --- a/src/server/game/Handlers/TradeHandler.cpp +++ b/src/server/game/Handlers/TradeHandler.cpp @@ -708,6 +708,15 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket) return; } + // PlayerScript Hook for checking traded items if we want to filter them in a custom module + if (!sScriptMgr->CanSetTradeItem(_player, item, tradeSlot)) + { + // Do not send TRADE_STATUS_TRADE_CANCELED because it will cause double display of "Transaction canceled" notification + // On the trade initiator screen + SendTradeStatus(TRADE_STATUS_CLOSE_WINDOW); + return; + } + my_trade->SetItem(TradeSlots(tradeSlot), item); } diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp index f5b777245..6f8a05ef5 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp @@ -1508,6 +1508,19 @@ bool ScriptMgr::CanInitTrade(Player* player, Player* target) return true; } +bool ScriptMgr::CanSetTradeItem(Player* player, Item* tradedItem, uint8 tradeSlot) +{ + auto ret = IsValidBoolScript([&](PlayerScript* script) + { + return !script->CanSetTradeItem(player, tradedItem, tradeSlot); + }); + + if (ret && *ret) + return false; + + return true; +} + void ScriptMgr::OnSetServerSideVisibility(Player* player, ServerSideVisibilityType& type, AccountTypes& sec) { ExecuteScript([&](PlayerScript* script) diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.h b/src/server/game/Scripting/ScriptDefines/PlayerScript.h index a0f9aa57a..eb0e6753e 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.h +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.h @@ -421,6 +421,16 @@ public: [[nodiscard]] virtual bool CanInitTrade(Player* /*player*/, Player* /*target*/) { return true; } + /** + * @brief This hook called just before finishing the handling of the action of a player setting an item in a trade slot + * + * @param player Contains information about the trade initiator Player + * @param tradedItem Contains information about the item set in the trade slot + * + * @return True if you want to continue setting the item in the trade slot, false if you want to cancel the trade + */ + [[nodiscard]] virtual bool CanSetTradeItem(Player* /*player*/, Item* /*tradedItem*/, uint8 /*tradeSlot*/) { return true; } + virtual void OnSetServerSideVisibility(Player* /*player*/, ServerSideVisibilityType& /*type*/, AccountTypes& /*sec*/) { } virtual void OnSetServerSideVisibilityDetect(Player* /*player*/, ServerSideVisibilityType& /*type*/, AccountTypes& /*sec*/) { } diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index a013178e0..0bb977fb9 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -440,6 +440,7 @@ public: /* PlayerScript */ bool CanJoinLfg(Player* player, uint8 roles, lfg::LfgDungeonSet& dungeons, const std::string& comment); bool CanEnterMap(Player* player, MapEntry const* entry, InstanceTemplate const* instance, MapDifficulty const* mapDiff, bool loginCheck); bool CanInitTrade(Player* player, Player* target); + bool CanSetTradeItem(Player* player, Item* tradedItem, uint8 tradeSlot); void OnSetServerSideVisibility(Player* player, ServerSideVisibilityType& type, AccountTypes& sec); void OnSetServerSideVisibilityDetect(Player* player, ServerSideVisibilityType& type, AccountTypes& sec); void OnPlayerResurrect(Player* player, float restore_percent, bool applySickness);