diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Server/Packets/AllPackets.h | 1 | ||||
-rw-r--r-- | src/server/game/Server/Packets/SpellPackets.cpp | 160 | ||||
-rw-r--r-- | src/server/game/Server/Packets/SpellPackets.h | 124 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 191 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 16 |
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); |