aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Server/Packets/AllPackets.h1
-rw-r--r--src/server/game/Server/Packets/SpellPackets.cpp160
-rw-r--r--src/server/game/Server/Packets/SpellPackets.h124
-rw-r--r--src/server/game/Spells/Spell.cpp191
-rw-r--r--src/server/game/Spells/Spell.h16
5 files changed, 389 insertions, 103 deletions
diff --git a/src/server/game/Server/Packets/AllPackets.h b/src/server/game/Server/Packets/AllPackets.h
index a3ec0f18793..63cd9c0ca4c 100644
--- a/src/server/game/Server/Packets/AllPackets.h
+++ b/src/server/game/Server/Packets/AllPackets.h
@@ -20,5 +20,6 @@
#include "QueryPackets.h"
#include "QuestPackets.h"
+#include "SpellPackets.h"
#endif // AllPackets_h__
diff --git a/src/server/game/Server/Packets/SpellPackets.cpp b/src/server/game/Server/Packets/SpellPackets.cpp
new file mode 100644
index 00000000000..048a928640d
--- /dev/null
+++ b/src/server/game/Server/Packets/SpellPackets.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "SpellPackets.h"
+#include "SharedDefines.h"
+#include "Spell.h"
+#include "SpellInfo.h"
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellMissStatus const& spellMissStatus)
+{
+ data << uint64(spellMissStatus.TargetGUID);
+ data << uint8(spellMissStatus.Reason);
+ if (spellMissStatus.Reason == SPELL_MISS_REFLECT)
+ data << uint8(spellMissStatus.ReflectStatus);
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::TargetLocation const& targetLocation)
+{
+ data << targetLocation.Transport.WriteAsPacked(); // relative position guid here - transport for example
+ data << targetLocation.Location.PositionXYZStream();
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellTargetData const& spellTargetData)
+{
+ data << uint32(spellTargetData.Flags);
+
+ if (spellTargetData.Unit)
+ data << spellTargetData.Unit->WriteAsPacked();
+
+ if (spellTargetData.Item)
+ data << spellTargetData.Item->WriteAsPacked();
+
+ if (spellTargetData.SrcLocation)
+ data << *spellTargetData.SrcLocation;
+
+ if (spellTargetData.DstLocation)
+ data << *spellTargetData.DstLocation;
+
+ if (spellTargetData.Name)
+ data << *spellTargetData.Name;
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::RuneData const& runeData)
+{
+ data << uint8(runeData.Start);
+ data << uint8(runeData.Count);
+ for (uint8 cooldown : runeData.Cooldowns)
+ data << uint8(cooldown);
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::MissileTrajectoryResult const& traj)
+{
+ data << float(traj.Pitch);
+ data << uint32(traj.TravelTime);
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellAmmo const& spellAmmo)
+{
+ data << uint32(spellAmmo.DisplayID);
+ data << uint32(spellAmmo.InventoryType);
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::CreatureImmunities const& immunities)
+{
+ data << uint32(immunities.School);
+ data << uint32(immunities.Value);
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellCastData const& spellCastData)
+{
+ data << spellCastData.CasterGUID.WriteAsPacked();
+ data << spellCastData.CasterUnit.WriteAsPacked();
+ data << uint8(spellCastData.CastID); // pending spell cast?
+ data << uint32(spellCastData.SpellID); // spellId
+ data << uint32(spellCastData.CastFlags); // cast flags
+ data << uint32(spellCastData.CastTime); // timestamp
+
+ if (spellCastData.HitTargets && spellCastData.MissStatus)
+ {
+ // Hit and miss target counts are both uint8, that limits us to 255 targets for each
+ // sending more than 255 targets crashes the client (since count sent would be wrong)
+ // Spells like 40647 (with a huge radius) can easily reach this limit (spell might need
+ // target conditions but we still need to limit the number of targets sent and keeping
+ // correct count for both hit and miss).
+ static std::size_t const PACKET_TARGET_LIMIT = std::numeric_limits<uint8>::max();
+ if (spellCastData.HitTargets->size() > PACKET_TARGET_LIMIT)
+ spellCastData.HitTargets->resize(PACKET_TARGET_LIMIT);
+
+ data << uint8(spellCastData.HitTargets->size());
+ for (ObjectGuid const& target : *spellCastData.HitTargets)
+ data << uint64(target);
+
+ if (spellCastData.MissStatus->size() > PACKET_TARGET_LIMIT)
+ spellCastData.MissStatus->resize(PACKET_TARGET_LIMIT);
+
+ data << uint8(spellCastData.MissStatus->size());
+ for (WorldPackets::Spells::SpellMissStatus const& status : *spellCastData.MissStatus)
+ data << status;
+ }
+
+ data << spellCastData.Target;
+
+ if (spellCastData.RemainingPower)
+ data << uint32(*spellCastData.RemainingPower);
+
+ if (spellCastData.RemainingRunes)
+ data << *spellCastData.RemainingRunes;
+
+ if (spellCastData.MissileTrajectory)
+ data << *spellCastData.MissileTrajectory;
+
+ if (spellCastData.Ammo)
+ data << *spellCastData.Ammo;
+
+ if (spellCastData.Immunities)
+ data << *spellCastData.Immunities;
+
+ if (spellCastData.CastFlags & CAST_FLAG_VISUAL_CHAIN)
+ {
+ data << uint32(0);
+ data << uint32(0);
+ }
+
+ if (spellCastData.Target.Flags & TARGET_FLAG_DEST_LOCATION)
+ data << uint8(0);
+ return data;
+}
+
+WorldPacket const* WorldPackets::Spells::SpellGo::Write()
+{
+ _worldPacket << Cast;
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Spells::SpellStart::Write()
+{
+ _worldPacket << Cast;
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/SpellPackets.h b/src/server/game/Server/Packets/SpellPackets.h
new file mode 100644
index 00000000000..2000ef9dd37
--- /dev/null
+++ b/src/server/game/Server/Packets/SpellPackets.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Scripts for spells with SPELLFAMILY_GENERIC which cannot be included in AI script file
+ * of creature using it or can't be bound to any player class.
+ * Ordered alphabetically using scriptname.
+ * Scriptnames of files in this file should be prefixed with "spell_gen_"
+ */
+
+#ifndef SpellPackets_h__
+#define SpellPackets_h__
+
+#include "Packet.h"
+#include "ObjectGuid.h"
+#include "Optional.h"
+
+namespace WorldPackets
+{
+ namespace Spells
+ {
+ struct SpellMissStatus
+ {
+ ObjectGuid TargetGUID;
+ uint8 Reason = 0;
+ uint8 ReflectStatus = 0;
+ };
+
+ struct RuneData
+ {
+ uint8 Start = 0;
+ uint8 Count = 0;
+ std::vector<uint8> Cooldowns;
+ };
+
+ struct MissileTrajectoryResult
+ {
+ uint32 TravelTime = 0;
+ float Pitch = 0.0f;
+ };
+
+ struct SpellAmmo
+ {
+ uint32 DisplayID = 0;
+ uint32 InventoryType = 0;
+ };
+
+ struct CreatureImmunities
+ {
+ uint32 School = 0;
+ uint32 Value = 0;
+ };
+
+ struct TargetLocation
+ {
+ ObjectGuid Transport;
+ Position Location;
+ };
+
+ struct SpellTargetData
+ {
+ uint32 Flags = 0;
+ Optional<ObjectGuid> Unit;
+ Optional<ObjectGuid> Item;
+ Optional<TargetLocation> SrcLocation;
+ Optional<TargetLocation> DstLocation;
+ Optional<std::string> Name;
+ };
+
+ struct SpellCastData
+ {
+ ObjectGuid CasterGUID;
+ ObjectGuid CasterUnit;
+ uint8 CastID = 0;
+ uint32 SpellID = 0;
+ uint32 CastFlags = 0;
+ uint32 CastTime = 0;
+ mutable Optional<std::vector<ObjectGuid>> HitTargets;
+ mutable Optional<std::vector<SpellMissStatus>> MissStatus;
+ SpellTargetData Target;
+ Optional<uint32> RemainingPower;
+ Optional<RuneData> RemainingRunes;
+ Optional<MissileTrajectoryResult> MissileTrajectory;
+ Optional<SpellAmmo> Ammo;
+ Optional<CreatureImmunities> Immunities;
+ };
+
+ class SpellGo final : public ServerPacket
+ {
+ public:
+ SpellGo() : ServerPacket(SMSG_SPELL_GO) { }
+
+ WorldPacket const* Write() override;
+
+ SpellCastData Cast;
+ };
+
+ class SpellStart final : public ServerPacket
+ {
+ public:
+ SpellStart() : ServerPacket(SMSG_SPELL_START) { }
+
+ WorldPacket const* Write() override;
+
+ SpellCastData Cast;
+ };
+ }
+}
+
+#endif // SpellPackets_h__
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 6f8322332b8..bbd290df5a4 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -47,6 +47,7 @@
#include "SpellHistory.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
+#include "SpellPackets.h"
#include "SpellScript.h"
#include "TemporarySummon.h"
#include "TradeData.h"
@@ -175,41 +176,42 @@ void SpellCastTargets::Read(ByteBuffer& data, Unit* caster)
Update(caster);
}
-void SpellCastTargets::Write(ByteBuffer& data)
+void SpellCastTargets::Write(WorldPackets::Spells::SpellTargetData& data)
{
- data << uint32(m_targetMask);
+ data.Flags = m_targetMask;
if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_CORPSE_ALLY | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_UNIT_MINIPET))
- data << m_objectTargetGUID.WriteAsPacked();
+ data.Unit = m_objectTargetGUID;
if (m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM))
{
+ data.Item = boost::in_place();
if (m_itemTarget)
- data << m_itemTarget->GetPackGUID();
- else
- data << uint8(0);
+ data.Item = m_itemTarget->GetGUID();
}
if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION)
{
- data << m_src._transportGUID.WriteAsPacked(); // relative position guid here - transport for example
- if (m_src._transportGUID)
- data << m_src._transportOffset.PositionXYZStream();
+ data.SrcLocation = boost::in_place();
+ data.SrcLocation->Transport = m_src._transportGUID;
+ if (!m_src._transportGUID.IsEmpty())
+ data.SrcLocation->Location = m_src._transportOffset;
else
- data << m_src._position.PositionXYZStream();
+ data.SrcLocation->Location = m_src._position;
}
if (m_targetMask & TARGET_FLAG_DEST_LOCATION)
{
- data << m_dst._transportGUID.WriteAsPacked(); // relative position guid here - transport for example
+ data.DstLocation = boost::in_place();
+ data.DstLocation->Transport = m_dst._transportGUID;
if (m_dst._transportGUID)
- data << m_dst._transportOffset.PositionXYZStream();
+ data.DstLocation->Location = m_dst._transportOffset;
else
- data << m_dst._position.PositionXYZStream();
+ data.DstLocation->Location = m_dst._position;
}
if (m_targetMask & TARGET_FLAG_STRING)
- data << m_strTarget;
+ data.Name = m_strTarget;
}
ObjectGuid SpellCastTargets::GetOrigUnitTargetGUID() const
@@ -4082,33 +4084,39 @@ void Spell::SendSpellStart()
if (m_spellInfo->RuneCostID && m_spellInfo->PowerType == POWER_RUNE)
castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it
- WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2));
+ WorldPackets::Spells::SpellStart packet;
+ WorldPackets::Spells::SpellCastData& castData = packet.Cast;
+
if (m_CastItem)
- data << m_CastItem->GetPackGUID();
+ castData.CasterGUID = m_CastItem->GetGUID();
else
- data << m_caster->GetPackGUID();
+ castData.CasterGUID = m_caster->GetGUID();
- data << m_caster->GetPackGUID();
- data << uint8(m_cast_count); // pending spell cast?
- data << uint32(m_spellInfo->Id); // spellId
- data << uint32(castFlags); // cast flags
- data << int32(m_timer); // delay?
+ castData.CasterUnit = m_caster->GetGUID();
+ castData.CastID = m_cast_count;
+ castData.SpellID = m_spellInfo->Id;
+ castData.CastFlags = castFlags;
+ castData.CastTime = m_timer;
- m_targets.Write(data);
+ m_targets.Write(castData.Target);
if (castFlags & CAST_FLAG_POWER_LEFT_SELF)
- data << uint32(ASSERT_NOTNULL(m_caster->ToUnit())->GetPower((Powers)m_spellInfo->PowerType));
+ castData.RemainingPower = ASSERT_NOTNULL(m_caster->ToUnit())->GetPower(static_cast<Powers>(m_spellInfo->PowerType));
if (castFlags & CAST_FLAG_AMMO)
- WriteAmmoToPacket(&data);
+ {
+ castData.Ammo = boost::in_place();
+ UpdateSpellCastDataAmmo(*castData.Ammo);
+ }
if (castFlags & CAST_FLAG_IMMUNITY)
{
- data << uint32(schoolImmunityMask);
- data << uint32(mechanicImmunityMask);
+ castData.Immunities = boost::in_place();
+ castData.Immunities->School = schoolImmunityMask;
+ castData.Immunities->Value = mechanicImmunityMask;
}
- m_caster->SendMessageToSet(&data, true);
+ m_caster->SendMessageToSet(packet.Write(), true);
}
void Spell::SendSpellGo()
@@ -4117,8 +4125,6 @@ void Spell::SendSpellGo()
if (!IsNeedSendToClient())
return;
- //TC_LOG_DEBUG("spells", "Sending SMSG_SPELL_GO id=%u", m_spellInfo->Id);
-
uint32 castFlags = CAST_FLAG_UNKNOWN_9;
// triggered spells with spell visual != 0
@@ -4152,78 +4158,82 @@ void Spell::SendSpellGo()
if (!m_spellInfo->StartRecoveryTime)
castFlags |= CAST_FLAG_NO_GCD;
- WorldPacket data(SMSG_SPELL_GO, 50); // guess size
+ WorldPackets::Spells::SpellGo packet;
+ WorldPackets::Spells::SpellCastData& castData = packet.Cast;
+
if (m_CastItem)
- data << m_CastItem->GetPackGUID();
+ castData.CasterGUID = m_CastItem->GetGUID();
else
- data << m_caster->GetPackGUID();
+ castData.CasterGUID = m_caster->GetGUID();
- data << m_caster->GetPackGUID();
- data << uint8(m_cast_count); // pending spell cast?
- data << uint32(m_spellInfo->Id); // spellId
- data << uint32(castFlags); // cast flags
- data << uint32(GameTime::GetGameTimeMS()); // timestamp
+ castData.CasterUnit = m_caster->GetGUID();
+ castData.CastID = m_cast_count;
+ castData.SpellID = m_spellInfo->Id;
+ castData.CastFlags = castFlags;
+ castData.CastTime = GameTime::GetGameTimeMS();
- WriteSpellGoTargets(&data);
+ UpdateSpellCastDataTargets(castData);
- m_targets.Write(data);
+ m_targets.Write(castData.Target);
if (castFlags & CAST_FLAG_POWER_LEFT_SELF)
- data << uint32(ASSERT_NOTNULL(m_caster->ToUnit())->GetPower((Powers)m_spellInfo->PowerType));
+ castData.RemainingPower = ASSERT_NOTNULL(m_caster->ToUnit())->GetPower(static_cast<Powers>(m_spellInfo->PowerType));
if (castFlags & CAST_FLAG_RUNE_LIST) // rune cooldowns list
{
+ castData.RemainingRunes = boost::in_place();
+
/// @todo There is a crash caused by a spell with CAST_FLAG_RUNE_LIST cast by a creature
//The creature is the mover of a player, so HandleCastSpellOpcode uses it as the caster
if (Player* player = m_caster->ToPlayer())
{
uint8 runeMaskInitial = m_runesState;
uint8 runeMaskAfterCast = player->GetRunesState();
- data << uint8(runeMaskInitial); // runes state before
- data << uint8(runeMaskAfterCast); // runes state after
+ castData.RemainingRunes->Start = runeMaskInitial; // runes state before
+ castData.RemainingRunes->Count = runeMaskAfterCast; // runes state after
+
for (uint8 i = 0; i < MAX_RUNES; ++i)
{
uint8 mask = (1 << i);
- if (mask & runeMaskInitial && !(mask & runeMaskAfterCast)) // usable before andon cooldown now...
+ if ((mask & runeMaskInitial) && !(mask & runeMaskAfterCast)) // usable before and on cooldown now...
{
// float casts ensure the division is performed on floats as we need float result
float baseCd = float(player->GetRuneBaseCooldown(i));
- data << uint8((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed
+ castData.RemainingRunes->Cooldowns.push_back(uint8((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255));
}
}
}
}
+
if (castFlags & CAST_FLAG_ADJUST_MISSILE)
{
- data << m_targets.GetElevation();
- data << uint32(m_delayMoment);
+ castData.MissileTrajectory = boost::in_place();
+ castData.MissileTrajectory->Pitch = m_targets.GetElevation();
+ castData.MissileTrajectory->TravelTime = m_delayMoment;
}
if (castFlags & CAST_FLAG_AMMO)
- WriteAmmoToPacket(&data);
-
- if (castFlags & CAST_FLAG_VISUAL_CHAIN)
{
- data << uint32(0);
- data << uint32(0);
- }
-
- if (m_targets.GetTargetMask() & TARGET_FLAG_DEST_LOCATION)
- {
- data << uint8(0);
+ castData.Ammo = boost::in_place();
+ UpdateSpellCastDataAmmo(*castData.Ammo);
}
// should be sent to self only
if (castFlags & CAST_FLAG_POWER_LEFT_SELF)
{
if (Player* player = m_caster->GetAffectingPlayer())
- player->SendDirectMessage(&data);
+ player->SendDirectMessage(packet.Write());
+
+ // update nearby players (remove flag)
+ castData.CastFlags &= ~CAST_FLAG_POWER_LEFT_SELF;
+ castData.RemainingPower = boost::none;
+ m_caster->SendMessageToSet(packet.Write(), false);
}
else
- m_caster->SendMessageToSet(&data, true);
+ m_caster->SendMessageToSet(packet.Write(), true);
}
-void Spell::WriteAmmoToPacket(WorldPacket* data)
+void Spell::UpdateSpellCastDataAmmo(WorldPackets::Spells::SpellAmmo& ammo)
{
uint32 ammoInventoryType = 0;
uint32 ammoDisplayID = 0;
@@ -4291,13 +4301,16 @@ void Spell::WriteAmmoToPacket(WorldPacket* data)
}
}
- *data << uint32(ammoDisplayID);
- *data << uint32(ammoInventoryType);
+ ammo.DisplayID = ammoDisplayID;
+ ammo.InventoryType = ammoInventoryType;
}
/// Writes miss and hit targets for a SMSG_SPELL_GO packet
-void Spell::WriteSpellGoTargets(WorldPacket* data)
+void Spell::UpdateSpellCastDataTargets(WorldPackets::Spells::SpellCastData& data)
{
+ data.HitTargets = boost::in_place();
+ data.MissStatus = boost::in_place();
+
// This function also fill data for channeled spells:
// m_needAliveTargetMask req for stop channelig if one target die
for (TargetInfo& targetInfo : m_UniqueTargetInfo)
@@ -4305,53 +4318,31 @@ void Spell::WriteSpellGoTargets(WorldPacket* data)
if (targetInfo.EffectMask == 0) // No effect apply - all immuned add state
// possibly SPELL_MISS_IMMUNE2 for this??
targetInfo.MissCondition = SPELL_MISS_IMMUNE2;
- }
- // Hit and miss target counts are both uint8, that limits us to 255 targets for each
- // sending more than 255 targets crashes the client (since count sent would be wrong)
- // Spells like 40647 (with a huge radius) can easily reach this limit (spell might need
- // target conditions but we still need to limit the number of targets sent and keeping
- // correct count for both hit and miss).
+ if (targetInfo.MissCondition == SPELL_MISS_NONE) // Add only hits
+ {
+ data.HitTargets->push_back(targetInfo.TargetGUID);
- uint32 hit = 0;
- size_t hitPos = data->wpos();
- *data << (uint8)0; // placeholder
- for (auto ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end() && hit < 255; ++ihit)
- {
- if (ihit->MissCondition == SPELL_MISS_NONE) // Add only hits
+ m_channelTargetEffectMask |= targetInfo.EffectMask;
+ }
+ else // misses
{
- *data << uint64(ihit->TargetGUID);
- m_channelTargetEffectMask |= ihit->EffectMask;
- ++hit;
+ WorldPackets::Spells::SpellMissStatus missStatus;
+ missStatus.TargetGUID = targetInfo.TargetGUID;
+ missStatus.Reason = targetInfo.MissCondition;
+ if (targetInfo.MissCondition == SPELL_MISS_REFLECT)
+ missStatus.ReflectStatus = targetInfo.ReflectResult;
+
+ data.MissStatus->push_back(missStatus);
}
}
- for (auto ighit = m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end() && hit < 255; ++ighit)
- {
- *data << uint64(ighit->TargetGUID); // Always hits
- ++hit;
- }
+ for (GOTargetInfo const& targetInfo : m_UniqueGOTargetInfo)
+ data.HitTargets->push_back(targetInfo.TargetGUID); // Always hits
- uint32 miss = 0;
- size_t missPos = data->wpos();
- *data << (uint8)0; // placeholder
- for (auto ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end() && miss < 255; ++ihit)
- {
- if (ihit->MissCondition != SPELL_MISS_NONE) // Add only miss
- {
- *data << uint64(ihit->TargetGUID);
- *data << uint8(ihit->MissCondition);
- if (ihit->MissCondition == SPELL_MISS_REFLECT)
- *data << uint8(ihit->ReflectResult);
- ++miss;
- }
- }
// Reset m_needAliveTargetMask for non channeled spell
if (!m_spellInfo->IsChanneled())
m_channelTargetEffectMask = 0;
-
- data->put<uint8>(hitPos, (uint8)hit);
- data->put<uint8>(missPos, (uint8)miss);
}
void Spell::SendLogExecute()
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 30eb56abb6b..62137799156 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -26,6 +26,16 @@
#include "SharedDefines.h"
#include <memory>
+namespace WorldPackets
+{
+ namespace Spells
+ {
+ struct SpellTargetData;
+ struct SpellAmmo;
+ struct SpellCastData;
+ }
+}
+
class Aura;
class AuraEffect;
class Corpse;
@@ -125,7 +135,7 @@ class TC_GAME_API SpellCastTargets
~SpellCastTargets();
void Read(ByteBuffer& data, Unit* caster);
- void Write(ByteBuffer& data);
+ void Write(WorldPackets::Spells::SpellTargetData& data);
uint32 GetTargetMask() const { return m_targetMask; }
void SetTargetMask(uint32 newMask) { m_targetMask = newMask; }
@@ -449,8 +459,8 @@ class TC_GAME_API Spell
void setState(uint32 state) { m_spellState = state; }
void DoCreateItem(uint32 i, uint32 itemtype);
- void WriteSpellGoTargets(WorldPacket* data);
- void WriteAmmoToPacket(WorldPacket* data);
+ void UpdateSpellCastDataTargets(WorldPackets::Spells::SpellCastData& data);
+ void UpdateSpellCastDataAmmo(WorldPackets::Spells::SpellAmmo& data);
bool CheckEffectTarget(Unit const* target, uint32 eff, Position const* losPosition) const;
bool CanAutoCast(Unit* target);