aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2024-07-02 11:12:16 +0200
committerShauren <shauren.trinity@gmail.com>2024-07-02 11:12:16 +0200
commit321161230fe557f930bb155729d9150c42c5758c (patch)
treeade16402c9a696eabe468c45e3d1ea48b858be40
parent70cff79ca6c578d51144f2a0ff0df5675aa06941 (diff)
Core/Spells: Implemented SPELL_ATTR9_ITEM_PASSIVE_ON_CLIENT
-rw-r--r--src/common/Containers/Utilities/ListUtils.h4
-rw-r--r--src/server/game/Entities/Player/Player.cpp34
-rw-r--r--src/server/game/Entities/Player/Player.h2
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp6
-rw-r--r--src/server/game/Server/Packets/ItemPackets.cpp23
-rw-r--r--src/server/game/Server/Packets/ItemPackets.h30
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp6
8 files changed, 98 insertions, 9 deletions
diff --git a/src/common/Containers/Utilities/ListUtils.h b/src/common/Containers/Utilities/ListUtils.h
index f5de0d42ec9..00a7d33c72f 100644
--- a/src/common/Containers/Utilities/ListUtils.h
+++ b/src/common/Containers/Utilities/ListUtils.h
@@ -24,7 +24,7 @@
namespace Trinity::Containers::Lists
{
template<typename T, typename Alloc = std::allocator<T>>
-inline typename std::list<T, Alloc>::iterator RemoveUnique(std::list<T, Alloc>& list, T const& value)
+inline typename std::list<T, Alloc>::iterator RemoveUnique(std::list<T, Alloc>& list, std::type_identity_t<T> const& value)
{
auto itr = std::find(list.begin(), list.end(), value);
if (itr != list.end())
@@ -34,7 +34,7 @@ inline typename std::list<T, Alloc>::iterator RemoveUnique(std::list<T, Alloc>&
}
template<typename T, typename Alloc = std::allocator<T>>
-inline typename std::forward_list<T, Alloc>::iterator RemoveUnique(std::forward_list<T, Alloc>& list, T const& value)
+inline typename std::forward_list<T, Alloc>::iterator RemoveUnique(std::forward_list<T, Alloc>& list, std::type_identity_t<T> const& value)
{
auto itr = list.before_begin();
auto toErase = std::next(itr);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 820934bd338..48ba015a43b 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -78,6 +78,7 @@
#include "Language.h"
#include "LanguageMgr.h"
#include "LFGMgr.h"
+#include "ListUtils.h"
#include "Log.h"
#include "Loot.h"
#include "LootItemStorage.h"
@@ -8376,6 +8377,17 @@ void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply,
TC_LOG_DEBUG("entities.player", "Player::ApplyEquipSpell: Player '{}' ({}) cast {} equip spell (ID: {})",
GetName(), GetGUID().ToString(), (item ? "item" : "itemset"), spellInfo->Id);
+ if (spellInfo->HasAttribute(SPELL_ATTR9_ITEM_PASSIVE_ON_CLIENT))
+ {
+ m_itemPassives.push_front(spellInfo->Id);
+ if (IsInWorld())
+ {
+ WorldPackets::Item::AddItemPassive addItemPassive;
+ addItemPassive.SpellID = spellInfo->Id;
+ SendDirectMessage(addItemPassive.Write());
+ }
+ }
+
CastSpell(this, spellInfo->Id, item);
}
else
@@ -8387,6 +8399,17 @@ void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply,
return; // and remove only not compatible at form change
}
+ if (spellInfo->HasAttribute(SPELL_ATTR9_ITEM_PASSIVE_ON_CLIENT))
+ {
+ Trinity::Containers::Lists::RemoveUnique(m_itemPassives, spellInfo->Id);
+ if (IsInWorld())
+ {
+ WorldPackets::Item::RemoveItemPassive removeItemPassive;
+ removeItemPassive.SpellID = spellInfo->Id;
+ SendDirectMessage(removeItemPassive.Write());
+ }
+ }
+
if (item)
RemoveAurasDueToItemSpell(spellInfo->Id, item->GetGUID()); // un-apply all spells, not only at-equipped
else
@@ -13841,6 +13864,16 @@ void Player::SendItemDurations()
(*itr)->SendTimeUpdate(this);
}
+void Player::SendItemPassives()
+{
+ if (m_itemPassives.empty())
+ return;
+
+ WorldPackets::Item::SendItemPassives sendItemPassives;
+ sendItemPassives.SpellID.assign(m_itemPassives.begin(), m_itemPassives.end());
+ SendDirectMessage(sendItemPassives.Write());
+}
+
void Player::SendNewItem(Item* item, uint32 quantity, bool pushed, bool created, bool broadcast /*= false*/, uint32 dungeonEncounterId /*= 0*/)
{
if (!item) // prevent crash
@@ -24468,6 +24501,7 @@ void Player::SendInitialPacketsAfterAddToMap()
SendAurasForTarget(this);
SendEnchantmentDurations(); // must be after add to map
SendItemDurations(); // must be after add to map
+ SendItemPassives(); // must be after add to map
if (GetMap()->IsRaid())
{
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index c9e3ca5a0d3..b3d3d9c7466 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1590,6 +1590,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void AddItemDurations(Item* item);
void RemoveItemDurations(Item* item);
void SendItemDurations();
+ void SendItemPassives();
void LoadCorpse(PreparedQueryResult result);
bool AddItem(uint32 itemId, uint32 count);
@@ -3138,6 +3139,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
EnchantDurationList m_enchantDuration;
ItemDurationList m_itemDuration;
+ std::forward_list<int32> m_itemPassives;
GuidUnorderedSet m_itemSoulboundTradeable;
std::unique_ptr<ResurrectionData> _resurrectionData;
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index e7130338f81..718cbf63e24 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -785,7 +785,7 @@ enum SpellAttr9 : uint32
SPELL_ATTR9_JUMPCHARGE__NO_FACING_CONTROL = 0x00800000, // TITLE JumpCharge - no facing control
SPELL_ATTR9_IGNORE_CASTER_HEALING_MODIFIERS = 0x01000000, // TITLE Ignore Caster Healing Modifiers
SPELL_ATTR9_DONT_CONSUME_CHARGE_IF_ITEM_DELETED = 0x02000000, /*NYI - some sort of bugfix attribute to prevent double item deletion?*/ // TITLE (Programmer Only) Don't consume charge if item deleted
- SPELL_ATTR9_UNK26 = 0x04000000, // TITLE Unknown attribute 26@Attr9
+ SPELL_ATTR9_ITEM_PASSIVE_ON_CLIENT = 0x04000000, // TITLE Item Passive On Client
SPELL_ATTR9_UNK27 = 0x08000000, // TITLE Unknown attribute 27@Attr9
SPELL_ATTR9_UNK28 = 0x10000000, // TITLE Unknown attribute 28@Attr9
SPELL_ATTR9_UNK29 = 0x20000000, // TITLE Unknown attribute 29@Attr9
diff --git a/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp b/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp
index 2140906aece..133026d02c1 100644
--- a/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp
+++ b/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp
@@ -1461,7 +1461,7 @@ TC_API_EXPORT EnumText EnumUtils<SpellAttr9>::ToString(SpellAttr9 value)
case SPELL_ATTR9_JUMPCHARGE__NO_FACING_CONTROL: return { "SPELL_ATTR9_JUMPCHARGE__NO_FACING_CONTROL", "JumpCharge - no facing control", "" };
case SPELL_ATTR9_IGNORE_CASTER_HEALING_MODIFIERS: return { "SPELL_ATTR9_IGNORE_CASTER_HEALING_MODIFIERS", "Ignore Caster Healing Modifiers", "" };
case SPELL_ATTR9_DONT_CONSUME_CHARGE_IF_ITEM_DELETED: return { "SPELL_ATTR9_DONT_CONSUME_CHARGE_IF_ITEM_DELETED", "(Programmer Only) Don't consume charge if item deleted", "" };
- case SPELL_ATTR9_UNK26: return { "SPELL_ATTR9_UNK26", "Unknown attribute 26@Attr9", "" };
+ case SPELL_ATTR9_ITEM_PASSIVE_ON_CLIENT: return { "SPELL_ATTR9_ITEM_PASSIVE_ON_CLIENT", "Item Passive On Client", "" };
case SPELL_ATTR9_UNK27: return { "SPELL_ATTR9_UNK27", "Unknown attribute 27@Attr9", "" };
case SPELL_ATTR9_UNK28: return { "SPELL_ATTR9_UNK28", "Unknown attribute 28@Attr9", "" };
case SPELL_ATTR9_UNK29: return { "SPELL_ATTR9_UNK29", "Unknown attribute 29@Attr9", "" };
@@ -1505,7 +1505,7 @@ TC_API_EXPORT SpellAttr9 EnumUtils<SpellAttr9>::FromIndex(size_t index)
case 23: return SPELL_ATTR9_JUMPCHARGE__NO_FACING_CONTROL;
case 24: return SPELL_ATTR9_IGNORE_CASTER_HEALING_MODIFIERS;
case 25: return SPELL_ATTR9_DONT_CONSUME_CHARGE_IF_ITEM_DELETED;
- case 26: return SPELL_ATTR9_UNK26;
+ case 26: return SPELL_ATTR9_ITEM_PASSIVE_ON_CLIENT;
case 27: return SPELL_ATTR9_UNK27;
case 28: return SPELL_ATTR9_UNK28;
case 29: return SPELL_ATTR9_UNK29;
@@ -1546,7 +1546,7 @@ TC_API_EXPORT size_t EnumUtils<SpellAttr9>::ToIndex(SpellAttr9 value)
case SPELL_ATTR9_JUMPCHARGE__NO_FACING_CONTROL: return 23;
case SPELL_ATTR9_IGNORE_CASTER_HEALING_MODIFIERS: return 24;
case SPELL_ATTR9_DONT_CONSUME_CHARGE_IF_ITEM_DELETED: return 25;
- case SPELL_ATTR9_UNK26: return 26;
+ case SPELL_ATTR9_ITEM_PASSIVE_ON_CLIENT: return 26;
case SPELL_ATTR9_UNK27: return 27;
case SPELL_ATTR9_UNK28: return 28;
case SPELL_ATTR9_UNK29: return 29;
diff --git a/src/server/game/Server/Packets/ItemPackets.cpp b/src/server/game/Server/Packets/ItemPackets.cpp
index b4bb558bac6..04c446ff3ae 100644
--- a/src/server/game/Server/Packets/ItemPackets.cpp
+++ b/src/server/game/Server/Packets/ItemPackets.cpp
@@ -402,3 +402,26 @@ void WorldPackets::Item::SetBankAutosortDisabled::Read()
{
Disable = _worldPacket.ReadBit();
}
+
+WorldPacket const* WorldPackets::Item::AddItemPassive::Write()
+{
+ _worldPacket << int32(SpellID);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Item::RemoveItemPassive::Write()
+{
+ _worldPacket << int32(SpellID);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Item::SendItemPassives::Write()
+{
+ _worldPacket << uint32(SpellID.size());
+ if (!SpellID.empty())
+ _worldPacket.append(SpellID.data(), SpellID.size());
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/ItemPackets.h b/src/server/game/Server/Packets/ItemPackets.h
index f0359be4575..60287883441 100644
--- a/src/server/game/Server/Packets/ItemPackets.h
+++ b/src/server/game/Server/Packets/ItemPackets.h
@@ -591,6 +591,36 @@ namespace WorldPackets
bool Disable = false;
};
+
+ class AddItemPassive final : public ServerPacket
+ {
+ public:
+ AddItemPassive() : ServerPacket(SMSG_ADD_ITEM_PASSIVE, 4) { }
+
+ WorldPacket const* Write() override;
+
+ int32 SpellID = 0;
+ };
+
+ class RemoveItemPassive final : public ServerPacket
+ {
+ public:
+ RemoveItemPassive() : ServerPacket(SMSG_REMOVE_ITEM_PASSIVE, 4) { }
+
+ WorldPacket const* Write() override;
+
+ int32 SpellID = 0;
+ };
+
+ class SendItemPassives final : public ServerPacket
+ {
+ public:
+ SendItemPassives() : ServerPacket(SMSG_SEND_ITEM_PASSIVES, 4) { }
+
+ WorldPacket const* Write() override;
+
+ std::vector<int32> SpellID;
+ };
}
}
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index f165019734b..d8de9ca04d1 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -1037,7 +1037,7 @@ void OpcodeTable::InitializeServerOpcodes()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACTIVE_SCHEDULED_WORLD_STATE_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ADDON_LIST_REQUEST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ADD_BATTLENET_FRIEND_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ADD_ITEM_PASSIVE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ADD_ITEM_PASSIVE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ADD_LOSS_OF_CONTROL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ADD_RUNE_POWER, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ADJUST_SPLINE_DURATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1957,7 +1957,7 @@ void OpcodeTable::InitializeServerOpcodes()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RECRUIT_A_FRIEND_FAILURE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFRESH_COMPONENT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFRESH_SPELL_HISTORY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_REMOVE_ITEM_PASSIVE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_REMOVE_ITEM_PASSIVE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REMOVE_SPELL_FROM_ACTION_BAR, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REPLACE_TROPHY_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REPORT_PVP_PLAYER_AFK_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
@@ -2007,7 +2007,7 @@ void OpcodeTable::InitializeServerOpcodes()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCRIPT_CAST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEASON_INFO, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SELL_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_ITEM_PASSIVES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_ITEM_PASSIVES, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_KNOWN_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_RAID_TARGET_UPDATE_ALL, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_RAID_TARGET_UPDATE_SINGLE, STATUS_NEVER, CONNECTION_TYPE_REALM);